Sunday, 21 August 2011

PrintCompilation JVM flag

While doing some performance checking on ThreeTen/JSR-310 I tried using the -XX:+PrintCompilation flag. In doing so, I discovered a certain lack of documentation due to a key Sun blog no longer being available. This blog mostly exists to recover that information from the internet archive.

The PrintCompilation flag exists to show basic information on when Hotspot compiles methods. Moazam Rajas wrote about the output format in his Sun blog, which was ported to Oracle. Unfortunately, only part of the original article was ported, losing the vital part. The internet archive appears to have the key part of original document:

But nevertheless, lets get back to the meat of the matter, the question on -XX:+PrintCompilation. I thought that a more detailed explanation of this flags output existed somewhere on the public internet, but maybe I just can't find it today. So I'll make a small attempt to explain the output.

The -XX:+PrintCompilation flag output looks something like this:

1  sb   java.lang.ClassLoader::loadClassInternal  (6 bytes) 	
2  b    java.lang.String::lastIndexOf  (12 bytes)
3  s!b  java.lang.ClassLoader::loadClass  (58 bytes)

Flags correspond to:

b    Blocking compiler (always set for client)	
*    Generating a native wrapper	
%    On stack replacement	
!    Method has exception handlers	
s    Synchronized method	

As Rajiv points on, once you find the offending method, you can tell the JVM to bypass it by creating a .hotspot_compiler file in your current working directory with an exclude statement. For example,

exclude java/lang/String indexOf

This would stop the java.lang.String.indexOf() method from being compiled.

Two other messages that appear are "made not entrant" and "made zombie". Again, finding out what they mean isn't easy, however an OTN forum discussion has a link to a comment by Cliff Click:

Zombie methods are methods whose code has been made invalid by class loading. Generally the server compiler makes aggressive inlining decisions of non-final methods. As long as the inlined method is never overridden the code is correct. When a subclass is loaded and the method overridden, the compiled code is broken for all future calls to it. The code gets declared "not entrant" (no future callers to the broken code), but sometimes existing callers can keep using the code. In the case of inlining, that's not good enough; existing callers' stack frames are "deoptimized" when they return to the code from nested calls (or just if they are running in the code). When no more stack frames hold PC's into the broken code it's declared a "zombie" - ready for removal once the GC gets around to it.

So, here is my updated table of flags:

b    Blocking compiler (always set for client)
*    Generating a native wrapper
%    On stack replacement (where the compiled code is running)
!    Method has exception handlers
s    Method declared as synchronized
n    Method declared as native
made non entrant    compilation was wrong/incomplete, no future callers will use this version
made zombie         code is not in use and ready for GC

If you've discovered anything else about -XX:+PrintCompilation then please add a comment!

Update 2011-09-26:
Kris Mok has done lots of investigation of the flag in far more detail than I have. Please read his notes which are very comprehensive and by JDK version!

4 comments:

  1. Now, you know:
    http://wikis.sun.com/display/HotSpotInternals/Home

    Rémi

    ReplyDelete
  2. That Sun link is now https://wikis.oracle.com/display/HotSpotInternals/Home.

    BTW is there a way to print when/if a method gets inlined into another?

    ReplyDelete
    Replies
    1. Ashwin,
      Try using -XX:+PrintInlining

      -Travis

      Delete
  3. Oracle-ized: https://wikis.oracle.com/display/HotSpotInternals/Home

    ReplyDelete