You have pretty much nailed it except that these options are picked up even if you start JVM in-process via a library call.

The fact that _JAVA_OPTIONS is not documented suggests that it is not recommended to use this variable, and I've actually seen people abuse it by setting it in their ~/.bashrc. However, if you want to get to the bottom of this problem, you can check the source of Oracle HotSpot VM (e.g. in OpenJDK7).

You should also remember that there is no guarantee other VMs have or will continue to have support for undocumented variables.

UPDATE 2015-08-04: To save five minutes for folks coming from search engines, _JAVA_OPTIONS trumps command-line arguments, which in turn trump JAVA_TOOL_OPTIONS.

Answer from mkalkov on Stack Overflow
🌐
Oracle
docs.oracle.com › javase › 8 › docs › technotes › guides › troubleshoot › envvars002.html
The JAVA_TOOL_OPTIONS Environment Variable
April 21, 2026 - When this environment variable ... argument. This environment variable allows you to specify the initialization of tools, specifically the launching of native or Java programming language agents using the -agentlib or -javaagent options....
🌐
Oracle
docs.oracle.com › en › java › javase › 21 › docs › specs › jvmti.html
JVM(TM) Tool Interface 21.0.0
January 20, 2026 - Since the command-line cannot always be accessed or modified, for example in embedded VMs or simply VMs launched deep within scripts, a JAVA_TOOL_OPTIONS variable is provided so that agents may be launched in these cases.
🌐
Baeldung
baeldung.com › home › java › core java › what is the difference between jdk_java_options and java_tool_options?
What Is the Difference Between JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS? | Baeldung
February 28, 2025 - If we check the variable after running the command, we’ll see that JDK_JAVA_OPTIONS no longer holds a value: ... $ JAVA_TOOL_OPTIONS="-Dvar1='Hi (JAVA_TOOL_OPTIONS)' -Dvar2='There (JAVA_TOOL_OPTIONS)'" java com.baeldung.TestEnvVar Picked up JAVA_TOOL_OPTIONS: -Dvar1='Hi (JAVA_TOOL_OPTIONS)' -Dvar2='There (JAVA_TOOL_OPTIONS)' var1 = 'Hi (JAVA_TOOL_OPTIONS)' var2 = 'There (JAVA_TOOL_OPTIONS)'
🌐
Server Fault
serverfault.com › questions › 1087798 › how-to-enable-java-agent-for-every-new-java-process-on-the-host
How to enable java agent for every new java process on the host? - Server Fault
This environment variable allows you to specify the initialization of tools, specifically the launching of native or Java programming language agents using the -agentlib or -javaagent options.
🌐
Amazon Web Services
docs.aws.amazon.com › aws lambda › developer guide › aws lambda functions › programming languages › building lambda functions with java › customize java runtime startup behavior for lambda functions
Customize Java runtime startup behavior for Lambda functions - AWS Lambda
To do this, append the following to the value of your JAVA_TOOL_OPTIONS environment variable: -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational · Lambda runtimes for Java 8, 11, 17, and 21 include a patch to mitigate the Log4Shell vulnerability (CVE-2021-44228) in Log4j, a popular Java ...
Find elsewhere
🌐
Java Code Geeks
javacodegeeks.com › home
JDK_JAVA_OPTIONS vs JAVA_TOOL_OPTIONS - Java Code Geeks
March 19, 2025 - Line 4: gradlew javadoc is executed successfully with the ‘-Xms1g‘ option. The earlier version of JDK ( before JDK 9 ) defines the JAVA_TOOL_OPTIONS environment variable that is appended to the CLI arguments to specify the initialization of tools, specifically the launching of native or Java programming language agents using the -agentlib or -javaagent options.
🌐
OpenJDK
bugs.openjdk.org › browse › JDK-8170832
Add a new launcher environment variable JAVA_OPTIONS
This proposes to introduce a new launcher enviornment variable `JAVA_OPTIONS` that is read by the java launcher. It will support multiple @files. Its content will be prepended to the actual command line; consistent with the current javac environment variable.
🌐
Codemia
codemia.io › home › knowledge hub › difference between _java_options, java_tool_options and java_opts
Difference between _JAVA_OPTIONS, JAVA_TOOL_OPTIONS and JAVA_OPTS | Codemia
January 27, 2025 - So the effective max heap is 1024m from _JAVA_OPTIONS, because it is appended last. This is why _JAVA_OPTIONS is considered dangerous: it silently overrides values you explicitly set on the command line. 1Priority (last wins for most flags): 21. JAVA_TOOL_OPTIONS (prepended, lowest priority) 32.
🌐
OpenJDK
bugs.openjdk.org › browse › jdk-4971166
[JDK-4971166] JAVA_TOOL_OPTIONS environment variable
Tool vendors need a uniform mechanism for adding options to a launch of the VM. Particularly, they need a mechanism whereby they can launch agents (such as a JVMTI agent) along with the VM, even if the VM is embedded. We currently prepend a _JAVA_OPTIONS environment variable but this is not ...
🌐
Oracle
docs.oracle.com › en › java › javase › 11 › troubleshoot › environment-variables-and-system-properties.html
C Environment Variables and System Properties
October 20, 2025 - In many environments, the command line is not readily accessible to start the application with the necessary command-line options. This often happens with applications that use embedded VMs (meaning they use the Java Native Interface (JNI) Invocation API to start the VM), or where the startup is deeply nested in scripts. In these environments the JAVA_TOOL_OPTIONS environment variable can be useful to augment a command line.
🌐
Oracle
docs.oracle.com › en › java › javase › 21 › docs › api › jdk.compiler › module-summary.html
jdk.compiler (Java SE 21 & JDK 21)
January 20, 2026 - When invoking the tool through its API, all components of the class path will be taken literally, and will be ignored if there is no matching directory or file. The -Xlint:paths option can be used to generate warnings about missing components. The following restrictions apply when invoking the compiler through the JavaCompiler interface.
🌐
GitHub
github.com › travis-ci › travis-cookbooks › issues › 895
Use JAVA_TOOL_OPTIONS instead of _JAVA_OPTIONS · Issue #895 · travis-ci/travis-cookbooks
August 31, 2017 - In #885 we introduced _JAVA_OPTIONS in an attempt to control JVM memory allocation. Documentation suggests that JAVA_TOOL_OPTIONS is actually recommended for these cases. The difference is pretty n...
Author   travis-ci
🌐
GitHub
github.com › GoogleContainerTools › jib › issues › 1833
Questions around environment variables ($JAVA_TOOL_OPTIONS) · Issue #1833 · GoogleContainerTools/jib
July 10, 2019 - - name: JAVA_OPTS value: -noverify -XX:TieredStopAtLevel=1 -XshowSettings:vm -XX:MaxRAMPercentage=55 -XX:InitialRAMPercentage=50 -XX:MinRAMPercentage=30 -XX:+UseContainerSupport
Author   GoogleContainerTools
🌐
ProgrammerZero Blog
programmerzero.hashnode.dev › javaopts-vs-javaoptions-vs-javatooloptions-whats-the-difference
Java ENV Variables: Key Differences - ProgrammerZero Blog
December 9, 2024 - If a script uses JAVA_OPTS, it appends its value to the JVM options for that particular application. Who is this guy?: A tool-specific variable that works with certain Java-based tools like Oracle WebLogic or IBM WebSphere.
🌐
Mise-en-place
mise.jdx.dev › lang › java.html
Java | mise-en-place
May 18, 2026 - mkdir ~/.local/share/mise/installs/java/21.0.1-open/Contents mkdir ~/.local/share/mise/installs/java/21.0.1-open/Contents/MacOS ln -s ~/.sdkman/candidates/java/21.0.1-open ~/.local/share/mise/installs/java/21.0.1-open/Contents/Home cp ~/.local/share/mise/installs/java/21.0.1-open/lib/libjli.dylib ~/.local/share/mise/installs/java/21.0.1-open/Contents/MacOS/libjli.dylib · Don't forget to make sure the cache is blocked and valid, by making sure an empty directory exists for your version in the mise cache: e.g. ... The following tool-options are available for the java backend.
🌐
OpenJDK
bugs.openjdk.org › browse › JDK-8288729
add-opens cannot be used in JAVA_TOOL_OPTIONS variable
A DESCRIPTION OF THE PROBLEM : Using the --add-opens option in JAVA_TOOL_OPTIONS environment variable leads to "Unrecognized option" error.