Series Posts

· 5 min read Posted by Tadeas Kriz

Gradle Properties

Understanding how Gradle properties work can save you a lot of time debugging. This post explains how to set properties and what their priorities are.
Diane Picchiottino -
Credit: Diane Picchiottino -

In our last post about Gradle, we talked about how configuring org.gradle.jvmargs can lead to unexpected out of memory errors. Now let’s talk about all the places Gradle gets its configuration from, so we can make sure you’re in full control of your build.

Most of your projects will have a file in the root. But not all the properties in that file have the same behavior.

The Configuring the Build Environment page in Gradle documentation tries to explain the different property types and their behavior. From our testing it behaves slightly differently than the page might lead you to believe. The table Priority for configurations looks like this:

1Command-line flagsCommand line--build-cacheThese have precedence over properties and environment variables.
2System propertiesProject Root DirsystemProp.http.proxyPort=443Stored in a file
3Gradle propertiesGRADLE_USER_HOME
Project Root Dir
org.gradle.logging.level=quietStored in a file
4Environment variablesEnvironmentGRADLE_OPTSSourced by the environment that executed Gradle

Once you start playing around with properties, you’ll find that this table misses some important information. For example, System properties are actually loaded from GRADLE_HOME and GRADLE_USER_HOME too, not just the Project Root Dir. And if you’re using a Gradle wrapper (invoking Gradle with ./gradlew which you probably do), then the file in $GRADLE_HOME is ignored.

With that in mind, let’s make our own tables. Yes, tables plural as we’ll capture behaviors of different property types. You see, the documentation speaks about Project, System and Gradle properties, as if they were completely separate. Instead we need to separate how are properties passed in, and how properties can be used in our build script. So let’s make a table for each property type.

System properties

System properties are used in JVM to pass in configuration using the -D argument. Though Gradle allows setting system properties in similar ways to project properties in files.

1Command-line flags-Da-system-property=cmdlineThese have precedence over property files and environment variables. file in $GRADLE_USER_HOMEsystemProp.a-system-property=gradle-user-homeDefaults to ~/.gradle/ if GRADLE_USER_HOME not set file in project root directorysystemProp.a-system-property=project-dirStored in a file file in $GRADLE_HOMEsystemProp.a-system-property=gradle-homeIgnored if started using a Gradle Wrapper
5Environment variablesGRADLE_OPTS="-Da-system-property=env"Sourced by the environment that executed Gradle

Project properties

There are many ways to access project properties in your build script. One such way is findProperty("a-project-property") which returns a value or null if not set.

1Command-line flags-Pa-project-property=cmdlineThese have precedence over property files and environment variables.
2System properties-Dorg.gradle.project.a-project-property=cmdline (any system property with org.gradle.project. prefix)See the table above for priorities file in $GRADLE_USER_HOMEa-project-property=gradle-user-homeDefaults to ~/.gradle/ if GRADLE_USER_HOME not set file in project root directorya-project-property=project-dirStored in a file file in $GRADLE_HOMEa-project-property=gradle-homeIgnored if started using a Gradle Wrapper
6Environment variablesORG_GRADLE_PROJECT_a_project_property=env (hyphens - not supported this way)Sourced by the environment that executed Gradle

Notice that project properties can be set using a system property. If the system property name starts with org.gradle.project., Gradle will automatically create a project property using the remaining suffix as its name. Consider the following two lines from a file:

You might expect that the a-project-property will have value world, but it’s hello instead. That’s because the project property set through a system property has a higher priority. When declared in a single file, it might not be that big of a deal. But it can easily be something you spend a lot of time debugging, if you have it set in multiple files, or even in GRADLE_OPTS.

Another interesting behavior is that anything you declare in one of the files, will be available as a project property. So findProperty("") will give you the same value as findProperty("a-project-property") in the above example. But if you pass in -Pa-project-property=cmdline to the Gradle invocation, findProperty("a-project-property") is overridden, while findProperty("") stays the same.

Gradle properties

Lastly we have the Gradle properties, which are special.

1Command-line flags--console=plainThese have precedence over property files and environment variables.
2System properties*-Dorg.gradle.console=plain* only on command-line or GRADLE_OPTS file in $GRADLE_USER_HOMEorg.gradle.console=plainDefaults to ~/.gradle/ if GRADLE_USER_HOME not set file in project root directoryorg.gradle.console=plainStored in a file file in $GRADLE_HOMEorg.gradle.console=plainIgnored if started using a Gradle Wrapper

Note that if configured using, it becomes a project property as well. That means that findProperty("org.gradle.console") would return a value. Similarly, if configured using a system property, we can use System.getProperty("org.gradle.console"). However, if that value is overridden by a command line flag, value we’d get from either wouldn’t be correct.

Common issues with $GRADLE_USER_HOME

Now that we looked at the priorities, we can look at one common issue caused by them. Notice that the in $GRADLE_USER_HOME has a higher priority than the one in your project’s root. It’s common that we consider whatever is closest to the project to have the highest priority, but that isn’t the case with Anything that you put into $GRADLE_USER_HOME/ will override your project’s and if you’re not careful, can lead to unexpected behavior. For example, let’s say you’ve set org.gradle.jvmargs in $GRADLE_USER_HOME/ so that all your Gradle daemons have the same JVM args. Some time passes and you’re working on a project that needs more heap size. So you update the project’s and nothing happens. Unless you remember that you’ve set it in $GRADLE_USER_HOME/, you might spend too much time trying to figure it out (don’t ask me how I know). It’d be really helpful if there was a way to ask Gradle to print all properties and where are they coming from. That’d make debugging this way easier.