SyntaxHighlighter

Monday, March 7, 2016

CompileCommand JVM option

CompileCommand is another JVM option that you can play with in conjunction (or not) with the famous PrintAssembly. But there is more...

In this article I will give you a description of all useful commands available with this option.

help

The first command you can try is the following:

java -XX:CompileCommand=help -version
  CompileCommand and the CompilerOracle allows simple control over
  what's allowed to be compiled.  The standard supported directives
  are exclude and compileonly.  The exclude directive stops a method
  from being compiled and compileonly excludes all methods except for
  the ones mentioned by compileonly directives.  The basic form of
  all commands is a command name followed by the name of the method
  in one of two forms: the standard class file format as in
  class/name.methodName or the PrintCompilation format
  class.name::methodName.  The method name can optionally be followed
  by a space then the signature of the method in the class file
  format.  Otherwise the directive applies to all methods with the
  same name and class regardless of signature.  Leading and trailing
  *'s in the class and/or method name allows a small amount of
  wildcarding.

  Examples:

  exclude java/lang/StringBuffer.append
  compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;
  exclude java/lang/String*.*
  exclude *.toString
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)

This is a start. But this online help is in fact quite incomplete. There is other commands/directives than those mentioned above.
To find out the others, we have to look at the documentation page here which is complete in this case.

dontinline

This command is useful if you want to control some behavior related to inlining. For example, JMH is using this directive through the CompilerControl annotation.
Let's take an example:


If we execute this code with the following JVM options:

-XX:UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining

If we add this JVM option:

-XX:CompileCommand="dontinline java.util.ArrayList::ensureCapacityInternal"

we will get:

No more inlining because disallowed by CompilerOracle where CompilerOracle is the CompileCommand JVM option.

inline

Same here with this command which try to force inlining on a specific method.
If we execute the previous code with the following JVM options:

-XX:UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining


We can see that grow method is not inlined in this context because considered as too big (above 35 byte codes). But if we add the CompileCommand:

-XX:CompileCommand="inline java.util.ArrayList::grow"

The result is the following:
The reason for inlining the method is now clear: force inline by CompilerOracle


print


The print command is in fact similar to the PrintAssembly JVM option. But the added value is the ability to specify the exact or prefix name method that we want to disassemble.  

-XX:CompileCommand="print java.util.ArrayList::add"

Wildcards are also allowed like mentioned in the online help:

-XX:CompileCommand="print java.util.ArrayList::*"

exclude

By default, all methods can be compiled if the compile threshold is reached. However we can exclude one or set of methods with the exclude command. Let's try with an example:

-XX:+PrintCompilation -XX:CompileCommand="exclude java.util.ArrayList::add"

The output will be:


compileonly

On the opposite, compileonly command allow to compile only the method specified in argument. Example:

-XX:+PrintCompilation -XX:CompileCommand="compileonly java.util.ArrayList::add"

The output will be:

Native methods are printed but no special operation is performed as JIT has nothing to do with them.

log

By default when you are using LogCompilation to output all compilation information from JIT, all methods compiled are included in this log. If we want to only output a specified method, we can use the log command in the same way than previous one.
Example:

-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:CompileCommand="log java.util.ArrayList::add"

The output file can be opened with JITWatch.

option

You can use this command to enable a JVM option only for the specified method or set of methods.
For example let's print the inlining tree for the ArrayList.add method:

XX:CompileCommand="option java.util.ArrayList::add,PrintInlining"


The output will be:
Very handy to avoid to be flooded by information.

CompileCommandFile

The previous commands can be combine into a file for convenience. By default the file is read from current directory with the name .hotspot_compiler. But you can specify your own file name with:

-XX:CompileCommandFile=MyCompilerFile.txt

This is an example of content:

And here is the output:

Update:

In JDK 9 there will be a new mechanism: Compiler Control. Thanks Mark Price for pointing me this JEP.

References