Skip to content

/flags/java/java-d-system-property

java -Dname=value: set a system property on the command line

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · openjdk version "17.0.20.1" 2026-08-18updated
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

bash
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

FormResult
-Dname=valueProperty name set to value
-DnameProperty name set to the empty string
-Dname=Also the empty string
"-Dname=a b"Value with spaces; quote the whole argument
-Dname=x -Dname=yThe last one wins
APIReturns
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 prints Picked up JAVA_TOOL_OPTIONS: ... on standard error, as the example shows. Useful in containers and CI.
  • JDK_JAVA_OPTIONS: read only by the java launcher (Java 9+), not by other JDK tools.
  • Build tools: mvn -Dskip.tests=true and ./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 example systemProperty in a Gradle test or run task).
  • 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 example file.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