Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Within a running JVM, how to programmatically determine the jvm options used at startup?

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:

  • Which garbage collector was used?
  • Was/is it actively doing cpu profiling?
  • Was/is it logging gc activity?
  • Was/is it in -Xint or -Xmixed mode?
  • Was/is -XX:ParallelGCThreads set -- if so, to what, and if not, what's the default for this build?
  • Was/is -XX:UseCompressedOops on or off?
  • etc.

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.

like image 982
Mickalot Avatar asked Jun 07 '13 23:06

Mickalot


People also ask

How do I find JVM options?

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.

Where is JVM options in Linux?

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.


3 Answers

You can get command line arguments by

ManagementFactory.getRuntimeMXBean().getInputArguments();
like image 36
ZhongYu Avatar answered Oct 24 '22 12:10

ZhongYu


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.

like image 109
Trevor Robinson Avatar answered Oct 24 '22 11:10

Trevor Robinson


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.

like image 30
Aleš Avatar answered Oct 24 '22 12:10

Aleš