Background: I'm doing some performance testing on a Java application that gets launched through several layers of indirection, such that I'm not entirely sure that the application is getting launched with the flags that I think it is. I'd like my application to include a sanity check (before it begins its performance test) and include in the results (after the test) information about how the JVM was tuned, such as:
-Xint
or -Xmixed
mode?-XX:ParallelGCThreads
set -- if so, to what, and if not, what's the default for this build?-XX:UseCompressedOops
on or off?Is there any way for Java code to (within a running JVM) query the actual options used for its containing JVM? (Assume that I can't see the command line that launched me, so I can't re-parse those flags.)
If there isn't a general-purpose way to determine this, answers that are specific to a particular JVM implementation are also welcome.
UPDATE:
It's important for the solution to be able to know what the default values are for any value that isn't explicitly supplied on the command-line. Otherwise, it's going to involve a lot of (error-prone) legwork to look up what the default value is for a given combination JVM/platform/version/architecture. I'm testing across a wide variety of JVMs, so I don't want to have to manually figure out what the default setting is for each parameter in each jvm release.
Non-Standard Java JVM Options Like the standard options, you're able to retrieve the full list of non-standard JVM command line options by calling java -X at the command line.
The directory server provides a means of configuring the Java Virtual Machine (JVM) and Java options for each command-line utility and for the directory server itself. The Java configuration is provided in a properties file, located at instance-dir /OUD/config/java.
You can get command line arguments by
ManagementFactory.getRuntimeMXBean().getInputArguments();
The following Java 7 code will list all of the JVM options returned by -XX:+PrintFlagsFinal
. It attempts to use reflection to access the package-protected Flag
helper class (available since Java 6), and falls back to HotSpotDiagnosticMXBean.getDiagnosticOptions()
if that doesn't work.
// load the diagnostic bean first to avoid UnsatisfiedLinkError
final HotSpotDiagnosticMXBean hsdiag = ManagementFactory
.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
List<VMOption> options;
try {
final Class<?> flagClass = Class.forName("sun.management.Flag");
final Method getAllFlagsMethod = flagClass.getDeclaredMethod("getAllFlags");
final Method getVMOptionMethod = flagClass.getDeclaredMethod("getVMOption");
getAllFlagsMethod.setAccessible(true);
getVMOptionMethod.setAccessible(true);
final Object result = getAllFlagsMethod.invoke(null);
final List<?> flags = (List<?>) result;
options = new ArrayList<VMOption>(flags.size());
for (final Object flag : flags) {
options.add((VMOption) getVMOptionMethod.invoke(flag));
}
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
| InvocationTargetException | ClassCastException e) {
if (hsdiag != null) {
// only includes writable external flags
options = hsdiag.getDiagnosticOptions();
} else {
options = Collections.emptyList();
}
}
final Map<String, VMOption> optionMap = new TreeMap<>();
for (final VMOption option : options) {
optionMap.put(option.getName(), option);
}
for (final VMOption option : optionMap.values()) {
System.out.println(option.getName() + " = " + option.getValue() + " (" +
option.getOrigin() + ", " +
(option.isWriteable() ? "read-write" : "read-only") + ")");
}
System.out.println(options.size() + " options found");
With 7u71, I get 663 options, or with -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
, 779.
You could use a JMX client (like VisualVM) and then call getVMOption(String name)
, see HotSpotDiagnosticMXBean.
Or, if you could pass in at least one set of flags to enable JVM logging, it should be --XX:+LogVMOutput -XX:LogFile=jvm.log
and then parse the output of the log from your app. The log contains all the flags/parameters used to startup the JVM.
Another option is to list the JVM process started by PID with ps -ef
and there you can see all the input argument of that process. That should work for any JVM type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With