/flags/java/java-d-system-property
java -Dname=value: set a system property on the command line
- tool
- Java
- command
- java
- flag
- -D<name>=<value>
- default
- only the JVM's built-in properties (java.version, user.dir, file.encoding...) are set
java -Dapp.env=prod Main sets the system property app.env to prod for that JVM; the program reads it with System.getProperty("app.env"). Properties configure your own code, libraries (-Dlogback.configurationFile=...) and the JDK itself (-Duser.timezone=UTC, -Dfile.encoding=UTF-8, -Dhttps.proxyHost=...). The option must come before the main class or -jar app.jar; after it, it is just a program argument.
Before and after the class name
cat > Props.java <<'EOF'
public class Props {
public static void main(String[] args) {
System.out.println("app.env = " + System.getProperty("app.env", "(not set)"));
System.out.println("app.debug = " + Boolean.getBoolean("app.debug"));
System.out.println("args = " + java.util.Arrays.toString(args));
}
}
EOF
echo "== no property"
java Props.java
echo "== -D before the source file"
java -Dapp.env=prod -Dapp.debug=true Props.java x
echo "== -D after the source file"
java Props.java -Dapp.env=prod
echo "== value with a space"
java "-Dapp.env=two words" Props.java
echo "== -Dapp.env (no value) and a repeated property"
java -Dapp.env Props.java | head -1 | sed 's/= $/= (empty string)/'
java -Dapp.env=x -Dapp.env=y Props.java | head -1
echo "== JAVA_TOOL_OPTIONS"
JAVA_TOOL_OPTIONS=-Dapp.env=fromenv java Props.java
echo "== space after -D"
java -D app.env=x Props.java; echo "exit: $?"Output
== no property app.env = (not set) app.debug = false args = [] == -D before the source file app.env = prod app.debug = true args = [x] == -D after the source file app.env = (not set) app.debug = false args = [-Dapp.env=prod] == value with a space app.env = two words app.debug = false args = [] == -Dapp.env (no value) and a repeated property app.env = (empty string) app.env = y == JAVA_TOOL_OPTIONS Picked up JAVA_TOOL_OPTIONS: -Dapp.env=fromenv app.env = fromenv app.debug = false args = [] == space after -D Error: Could not find or load main class app.env=x Caused by: java.lang.ClassNotFoundException: app.env=x exit: 1
Placed after the file name, -Dapp.env=prod arrives in args and the property stays unset. A space between -D and the name is a classic typo: the launcher accepts the lone -D and takes the next word, app.env=x, as the class to run, failing with Could not find or load main class app.env=x (see that error).
Syntax and reading
| Form | Result |
|---|---|
| -Dname=value | Property name set to value |
| -Dname | Property name set to the empty string |
| -Dname= | Also the empty string |
| "-Dname=a b" | Value with spaces; quote the whole argument |
| -Dname=x -Dname=y | The last one wins |
| API | Returns |
|---|---|
| System.getProperty("name") | The value, or null if not set |
| System.getProperty("name", "default") | The value, or the default |
| Boolean.getBoolean("name") | true only if the property equals "true" (ignoring case) |
| Integer.getInteger("name", 10) | The value parsed as int, or 10 |
| System.getProperties() | All properties, including the JVM ones |
Other places that set properties
JAVA_TOOL_OPTIONS: read by every JVM, which printsPicked up JAVA_TOOL_OPTIONS: ...on standard error, as the example shows. Useful in containers and CI.JDK_JAVA_OPTIONS: read only by thejavalauncher (Java 9+), not by other JDK tools.- Build tools:
mvn -Dskip.tests=trueand./gradlew -Dorg.gradle.jvmargs=...use the same syntax, but those properties belong to the Maven or Gradle JVM, not to the application they build or run. Pass application properties through the plugin configuration (for examplesystemPropertyin a Gradletestorruntask). - Code:
System.setProperty("name", "value")at run time, which only helps for code that reads the property later.
Pitfalls
- Some JDK properties are read once at start-up and cannot be changed later with
System.setProperty(for examplefile.encoding, which decides the default charset); set them with-D. - Properties are visible to anyone who can list processes (
ps, Task Manager show the command line). Do not pass passwords or API keys with-D; use a file or a secret store. - On PowerShell, quote the option (
java "-Dapp.env=prod" Main), because PowerShell can split an unquoted argument that starts with-and contains a dot.
FAQ
Why is System.getProperty returning null although I passed -D?
Most often the -D option was written after the class name or after -jar app.jar, so it reached main as a program argument. Move it before the class or -jar. Also check the spelling: property names are case-sensitive.
What is the difference between -D properties and environment variables?
-D sets a Java system property, read with System.getProperty, and applies only to that JVM. Environment variables come from the operating system, are read with System.getenv and are inherited by child processes. Frameworks such as Spring Boot read both.
How do I pass a value with spaces?
Quote the whole option for the shell: java "-Dapp.title=My App" Main. The quotes are removed by the shell and the JVM receives one argument.
Sources
- docs.oracle.comdocs.oracle.com/en/java/javase/17/docs/specs/man/java.html#standard-options-for-java
- docs.oracle.comdocs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#getProperty(java.lang.String,java.lang.String)
- docs.oracle.comdocs.oracle.com/en/java/javase/17/docs/specs/man/java.html#using-the-jdk_java_options-launcher-environment-variable