Thursday, August 28, 2014

JDK 8: Revisiting ReservedCodeCacheSize and CompileThreshold

In[1], someone has commented that:
Did you specify any extra JVM parameters to reach the state of full CodeCache? Some comments on the internet indicate this happens if you specify too low "-XX:CompileThreshold" and too much bytecode gets compiled by HotSpot very early.

when the following warning was seen:
VM warning: CodeCache is full. Compiler has been disabled.

In this article, we will look at tuning CompileThreshold and ReservedCodeCacheSize in JDK 8.


CompileThreshold



By default, CompileThreshold is set to be 10,000:

     intx CompileThreshold     = 10000       {pd product}

As described in [2], we know {pd product} means "platform-dependent product option".  Our platfrom is linux-x64 and that will be used for this discussion.

Very often, you see people setting the threshold lower.  For example
-XX:CompileThreshold=8000
Why?  Since the JIT compiler does not have time to compile every single method in an application, all code starts out initially running in the interpreter, and once it becomes hot enough it gets scheduled for compilation. To help determine when to convert bytecodes to compiled code, every method has two counters:
  • Invocation counter
    • Which is incremented every time a method is entered
  • Backedge counter
    •  Which is incremented every time control flow moves from a higher bytecode index to a lower one
Whenever either counter is incremented by the interpreter it checks them against a threshold, and if they cross this threshold, the interpreter requests a compile of that method.

The threshold used for the invocation counter is called the CompileThreshold, the backedge counter uses a more complex formula derived from CompileThreshold and OnStackReplacePercentage.  So, if you set the threshold lower, HotSpot compiles methods earlier.  And, in some cases, that can help the performance of server codes.

ReservedCodeCacheSize


A code cache is where JVM uses to store the native code generated for compiled methods.  As described in [3], to improve an application's performance, you can set the "reserved" code cache size:
  • -XX:ReservedCodeCacheSize=256m
when tiered compilation is enabled for the HotSpot.  Basically it sets the maximum size for the compiler's code cache.  In [4], we have shown that an application can run faster if tiered compilation is enabled in a server environment.  However, code cashe size also needs to be specified larger.

What's New in JDK 8?


We have seen people setting the following JVM options:
  • -XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation
or
  • -XX:CompileThreshold=8000 
in JDK 7.  In JDK 8, do we still need to set them?  The answer is that it depends on the platform.  On linux-x64 platforms, those setting are no longer necessary.  Here we will describe why.

In JDK 8, it chooses the following default values for linux-x64 platforms:

    bool TieredCompilation        = true       {pd product}     
    intx CompileThreshold         = 10000      {pd product}
    uintx ReservedCodeCacheSize   = 251658240  {pd product}


When tiered compilation is enabled, two things happen:
  1. CompileThreshold is ignored
  2. A bigger code cache is needed.  Internally, HotSpot will set it to be 240 MB (i.e., 48 MB * 5)
That's why we say that people don't need to set the following options anymore in JDK8:
  • -XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation 
or
  • -XX:CompileThreshold=8000

Noted that “reserved” code cache is just an address space reservation, it does not really consume any additional physical memory unless it’s used.  On 64-bit platforms, it doesn’t hurt at all to set a higher value.  However, if you have set cache size to be too small, you will definitively see the negative impact on your application's performance.

Acknowledgement


Some writings here are based on the feedback from Igor Veresov and Vladimir Kozlov. However, the author would assume the full responsibility for the content himself.

References

  1. VM warning: CodeCache is full. Compiler has been disabled.
  2. HotSpot: What Does {pd product} Mean?  (Xml and More)
  3. Performance Tuning with Hotspot VM Option: -XX:+TieredCompilation (Xml and More
  4. A Case Study of Using Tiered Compilation in HotSpot  (Xml and More)
  5. Useful JVM Flags – Part 4 (Heap Tuning)
  6. g1gc logs - Ergonomics -how to print and how to understand 
  7. G1 GC Glossary of Terms
  8. Learn More About Performance Improvements in JDK 8 
  9. HotSpot Virtual Machine Garbage Collection Tuning Guide
  10. Other JDK 8 articles on Xml and More
  11. Tuning that was great in old JRockit versions might not be so good anymore
    • Trying to bring over each and every tuning option from a JR configuration to an HS one is probably a bad idea.
    • Even when moving between major versions of the same JVM, we usually recommend going back to the default (just pick a collector and heap size) and then redoing any tuning work from scratch (if even necessary).

Wednesday, August 27, 2014

JDK 8: UseCompressedClassPointers vs. UseCompressedOops

A new JVM option was introduced into JDK 8 after PermGen removal:
UseCompressedClassPointers
In this article, we will discuss the difference between  UseCompressedOops and UseCompressedClassPointers.

Default Values


As described in [2], you can find out the default values of UseCompressedClassPointers and UseCompressedOops:

     bool UseCompressedClassPointers           := true   {lp64_product}
     bool UseCompressedOops                    := true   {lp64_product}

Our platform is linux-x64 and these options are both set to be true based on ergonomics.

UseCompressedOops vs. UseCompressedClassPointers


CompressedOops are for the compression of pointers to objects in the Java Heap.  Class data is no
longer in the Java Heap and the compression of pointers to class data is done under the flag
UseCompressedClassPointers.  In next sections, we will discuss them in more details.

Oops and Compressed Oops


Oops are "ordinary" object pointers.  Specifically, a pointer into the GC-managed heap. Implemented as a native machine address, not a handle. Oops may be directly manipulated by compiled or interpreted Java code, because the GC knows about the liveness and location of Oops within such code.  Oops can also be directly manipulated by short spans of C/C++ code, but must be kept by such code within handles across every safepoint.

Compressed Oops represent managed pointers (in many but not all places in the JVM) as 32-bit values which must be scaled by a factor of 8 and added to a 64-bit base address to find the object they refer to in Java Heap.

Compressed Class Pointers


Objects (in its 2nd word) have a pointer  to VM Metadata class, which can be compressed.  If compressed, it uses a base which points to the Compressed Class Pointer Space.

Before we continue, you need to know what Metaspace and Compressed Class Pointer Space  are. A Compressed Class Pointer Space (which is logically part of Metaspace) is introduced for 64 bit platforms. Whereas the Compressed Class Pointer Space contains only class metadata, the Metaspace can contain all other large class metadata including methods, bytecode etc.

For 64 bit platforms, the default behavior is using compressed (32 bit) object pointers (-XX:+UseCompressedOops) and compressed (32 bit) class pointers (-XX:+UseCompressedClassPointers).  However, you can modify default settings if you like.  When you do  modify them, be warned that there is a dependency between the two options—i.e., UseCompressedOops must be on for UseCompressedClassPointers to be on.

To summarize it, the differences between Metaspace and Compressed Class Pointer Space are :[3]
  • Compressed Class Pointer Space contains only class metadata
    • InstanceKlass, ArrayKlass
      • Only when UseCompressedClassPointers true
      • These include Java virtual tables for performance reasons
  • Metaspace contains all other class metadata that can be large.
    • Methods, Bytecodes, ConstantPool ...

 

References

  1. HotSpot: Monitoring and Tuning Metaspace in JDK 8 (Xml and More)
  2. What Are the Default HotSpot JVM Values?
  3. Metaspace in Java 8 (good)  
  4. HotSpot Glossary of Terms 
  5. VM Class Loading
  6. Learn More About Performance Improvements in JDK 8 
  7. Garbage-First Garbage Collector Tuning
  8. Understanding Compressed References (JRockit)
    • Similar to HotSpot's CompressedOops, Jrockit uses -XXcompressedRefs command option.

Friday, August 22, 2014

HotSpot: Sizing System Dictionary in JDK 8

The system dictionary is an internal JVM data structure which holds all the classes loaded by the system.  As described in JDK-7114376,[1]
The System Dictionary hashtable bucket array size is fixed at 1009. This value is too small for large programs with many names, too large for small programs and just about right for medium sized ones. The default should remain at 1009, but it should be possible to override it on the command line.
Finally, this has happened in JDK 8 and you can set hashtable bucket array size to be larger if you have more classes loaded in your applications by using:[2]
  • -XX:+UnlockExperimentalVMOptions  -XX:PredictedLoadedClassCount=<#>
This can help calls like Class.forName(), which do lookups into this data structure.

In this article, we will look into sizing system dictionary in more details.

Performance of System Dictionary


In 1.4.2, there were some performance enhancements.  One of them is making system dictionary reads lock-free.[3] From this enhancement, you probably can guess that tuning system dictionary could be important to the JVM's performance.

The current number of buckets in hash table for system dictionary is set to be 1009 by default, which is relatively small for an application which has 49987 classes loaded as shown below:

Loaded   Bytes Unloaded   Bytes       Time
49987 110488.8     2453  7743.8     105.24

From the experience, we know:[5]
In a good hash table, each bucket has zero or one entries, and sometimes two or three, but rarely more than that.
 Assuming the average ideal length of buckets is three, the hashtable bucket array size then should be:
Ideal hashtable bucket array size = 49987 / 3 = 16662

 

System Dictionary Tuning


Seeing 49987classes loaded in our application at end of its run, we decided to set:
-XX:PredictedLoadedClassCount=16661 (a prime)

Note that PredictedLoadedClassCount is an experimental flag.  So, you also need to set:
-XX:+UnlockExperimentalVMOptions
before it in the command line.

When the JVM allocates memory, the largest chunk is the java heap. The system dictionary is in C heap and it is the loaded class cache. The goal of setting PredictedLoadedClassCount flag is to increase the size of the system dictionary in order to make lookups of loaded classes faster. Before every class being loaded, it requires a checking to see if the class is already loaded.  Larger system dictionary will improve JVM performance during this class loading and resolution phase.

Note that the total number of entries in the hashtable does not change— that is based on the number of loaded classes. What sizing of system dictionary do is to increase the spread of the entries so that the average length of the buckets under a single hash result could be reduced. This would reduce the time it takes to find a given entry.

How to Find Number of Loaded Classes?


There are multiple ways to find out number of loaded classes in an application.  For example, you can use -Xverbose:class to determine what classes are loaded.   Another way to find out is what we have done in this article by setting -XX:+PerfDataSaveToFile and then use "jstat -class" command to decipher the class statistics offline:

$<snipped>/jdk-hs/bin/jstat -class file:////slot/myserver/appmgr/APPTOP/instance/domains/slcaf977.us.oracle.com/CRMDomain/hsperfdata_9872

Loaded   Bytes Unloaded   Bytes       Time
49987 110488.8     2453  7743.8     105.24

Acknowledgement


Some writings here are based on the feedback from Mikael Gerdin and Karen Kinnear. However, the author would assume the full responsibility for the content himself.

References

  1. Make system dictionary hashtable bucket array size configurable  (JDK-7114376)
  2. Tuning the JVM (at 43:02 mark)
  3. Java 2 Platform, Standard Edition (J2SE Platform), version 1.4.2 Performance White Paper 
  4. The Class Loader Subsystem 
  5. Hash table (Wikipedia) 
  6. VM Class Loading
    • Actually, the HotSpot VM maintains three main hash tables to track class loading
      • SystemDictionary  
      • PlaceholderTable 
      • LoaderConstraintTable
  7. Garbage-First Garbage Collector Tuning

Wednesday, August 20, 2014

HotSpot: A Case Study of MetaspaceSize Tuning in JDK 8

This article is one of the Metaspace series in JDK 8 on Xml and More.  Please read previous articles (i.e. [1, 2, 3]) for the background information.

Here we use a case study to show you what we mean by:
Proper monitoring and tuning of the Metaspace is still required in order to limit the frequency or delay the garbage collections of metaspace.

 

JVM Setup


We have used the following print options:
  •  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
to generate GC log files.  Besides that, we have set:
  •  -XX:MetaspaceSize=128m
to specify the initial high water mark to trigger metaspace cleanup by inducing a GC event.

In the GC log file, you can find the following entries:

[Metaspace: 21013K->21013K(1069056K)]

The first value shows you the previously used size before GC, the second value shows you the current used size and the last value shows you the current reserved size.

Before Tuning


Below is the experiment running with all default values.  As you can see, there are six Full GC events triggered by "Metadata GC Threshold" being reached.  The initial high water mark was set by the default MetaspaceSize (i.e.,  21807104 Bytes).  So, the first Full GC event was induced when committed memory of all metaspaces reaches the initial high water mark.  To find HotSpot's default option values, read [4].

3.112: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 21013K->21013K(1069056K)]
5.440: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 34645K->34645K(1081344K)]
11.921: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 58159K->58152K(1101824K)]
18.321: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 97038K->97038K(1136640K)]
51.761: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 160475K->155432K(1193984K)]
319.406: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 267854K->267854K(1288192K)]



Note that the unit on X-axis is seconds and Y-axis KBytes.

After Tuning


Here we have set the experiment with the following extra option:
  • -XX:MetaspaceSize=128m
Note that 128M is bigger than default value (i.e., 21807104 Bytes).  Because of the setting, we have reduced the frequency and delayed garbage collections due to "Metadata GC Threshold" being reached.  


25.863: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 127978K->126460K(1165312K)]
81.254: [Full GC (Metadata GC Threshold) ...]
   [Eden: ..., [Metaspace: 213481K->209918K(1241088K)]
3486.808: [Full GC (Allocation Failure) ...]
   [Eden: ..., [Metaspace: 306929K->298136K(1327104K)]
3631.001: [Full GC (Allocation Failure) ...]
   [Eden: ..., [Metaspace: 299979K->298792K(1329152K)]



Why to Tune?


So, you may ask what's the deal with tuning MetaspaceSize.  Yes, it's just setting the initial high water mark.  Later HotSpot will adjust high water mark based on ergonomics.  Hopefully, when HotSpot's ergonomics becomes more matured, no tuning is necessary at all.  But, even in that case, you may still want to set MetaspaceSize for some occasions.  One of them is when you run a benchmark in a short period and your focus may be on other GC activities than meta data being loaded or unloaded.

References

  1. HotSpot: Understanding Metaspace in JDK 8
  2. HotSpot: Monitoring and Tuning Metaspace in JDK 8
  3. jstat Tool: New Metaspace Statistics from -gc Option
  4. What Are the Default HotSpot JVM Values?
  5. VM Class Loading 

Friday, August 15, 2014

jstat Tool: New Metaspace Statistics from -gc Option

In [1], we have shown one way of estimating the size of metaspace[2] using the following command:
jstat -class
However, there are other metadata or implementation overhead (i.e., MetaBlock overhead) not accounted for in the reported sizes.

In this article, we will introduce another way of monitoring the sizes needed for "Metaspace" and "Class Space".

Heap Statistics Reported by PrintGC


As described in [2], the following heap statistics would be printed at the exit of JVM if you have enabled PringGC (i.e., PrintGCDetails or PrintHeapAtGC):

Heap
 garbage-first heap   total 2097152K, used 1680819K [0x0000000080000000, 0x0000000100000000, 0x0000000100000000)
  region size 4096K, 27 young (110592K), 9 survivors (36864K)
 Metaspace       used 327768K, capacity 340303K, committed 340780K, reserved 1349632K
  class space    used 37537K, capacity 40670K, committed 40832K, reserved 1048576K

jstat -gc Command


jstat -gc can be used to display Garbage-collected heap statistics.  In JDK 8, it would display Metaspace's statistics, but not PermGen's.

-bash-3.2$ jstat -gc 18990 1000 3
Warning: Unresolved Symbol: sun.gc.generation.2.space.0.capacity substituted NaN
Warning: Unresolved Symbol: sun.gc.generation.2.space.0.used substituted NaN
 S0C   S1C      S0U   S1U     EC       EU       OC         OU           PC     PU  
 0.0   16384.0  0.0   16384.0 94208.0  12288.0  1986560.0  1783935.8    �      �     
 0.0   16384.0  0.0   16384.0 94208.0  57344.0  1986560.0  1775743.8    �      �     
 0.0   16384.0  0.0   16384.0 94208.0  69632.0  1986560.0  1775743.8    �      �      

At the first try, it has printed the above three lines.  However, the default jstat was run, which belongs to JDK 7.  So, you still see headers such as "PC" and "PU".  Also, you could see some gibberish text because of "unresolved symbols."  To run jstat, you need to use the correct version (i.e., from your JDK 8 installation).  After correcting this error, we have seen: 

-bash-3.2$ cd JVMs/
-bash-3.2$ jdk-hs/bin/jstat  -gc 18990 1000 3
 S0C   S1C      S0U   S1U     EC       EU       OC         OU         MC       MU       CCSC    CCSU  
 0.0   28672.0  0.0   28672.0 163840.0 45056.0  1904640.0  1663244.2  340992.0 327753.1 40960.0 37549.0  
 0.0   28672.0  0.0   28672.0 163840.0 77824.0  1904640.0  1663244.2  340992.0 327753.1 40960.0 37549.0
 0.0   28672.0  0.0   28672.0 163840.0 86016.0  1904640.0  1663244.2  340992.0 327753.1 40960.0 37549.0 


Note that we now see "MC", "MU", "CCSC", and "CCSU" instead of "PC" and "PU".

Meaning of "MC", "MU", "CCSC", and "CCSU"


There is no good documentation on what they mean yet.  But, a good guess would be:
  • MC (Metaspace Committed)
  • MU (Metaspace Used)
  • CCSC (Compressed Class Space Committed)
  • CCSU (Compressed Class Space Used)

If you check the values printed out from "jstat -gc" and the values printed out at JVM's exit time.  They have similar values.  Note that the "jstat -gc" command was issued close to the end of our JVM run.

To learn more about these new headers, read [2].

Acknowledgement


Some writings here are based on the feedback from Jon Masamitsu. However, the author would assume the full responsibility for the content himself.

References

  1. HotSpot: Monitoring and Tuning Metaspace in JDK 8
  2. HotSpot: Understanding Metaspace in JDK 8
  3. jstat - Java Virtual Machine Statistics Monitoring Tool
  4. Interpreting jstat results
  5. JavaOne Wednesday: Permanent Generation Removal Overview
  6. HotSpot: A Case Study of MetaspaceSize Tuning in JDK 8

Thursday, August 14, 2014

HotSpot: Understanding Metaspace in JDK 8

In JDK 8, it will print out the following information when JVM exits:
Heap
 <snipped> 
 Metaspace       used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 262K, capacity 386K, committed 512K, reserved 1048576K
if you have enabled GC printing using:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
Note that if PrintGCDetails is enabled, PrintGC[1] is also enabled.

In this article, we will examine what the above lines mean.

Metaspace


Internal JVM memory management is, to a large extent, kept off the Java heap and allocated natively in the operating system, through system calls like malloc or mmap. This non-heap system memory allocated by the JVM is referred to as native memory. Similar to the Oracle JRockit and IBM JVM's, the JDK 8 HotSpot JVM is now using native memory for the representation of class metadata, which is called Metaspace.[2,4]

In JDK 8, Hotspot explicitly manages the space used for metadata. Space is requested from the OS and then divided into chunks. A class loader will allocate space for metadata from its chunks (a chunk is to bound to a specific class loader). When classes are unloaded for a class loader, its chunks are recycled for reuse or returned to the OS.   Note that metadata uses mmap'ed space and not malloc'ed space.

Used/Capacity/Committed/Reserved


When JVM exits, it prints the following information if you have enabled GC printing:
 Metaspace       used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 262K, capacity 386K, committed 512K, reserved 1048576K
In the “Metaspace” line, the “used” is the amount of space used for loaded classes and other metadata. The “capacity” is the space available for metadata in currently allocated chunks. The “committed” value is the amount of space available for chunks. The “reserved” is the amount of space reserved (but not necessarily committed) for metadata. On the “class space” line, those values are the corresponding values for the class area in Metaspace when compressed class pointers are used.

Mataspace is dynamically managed by HotSpot.  Metadata are deallocated when their class loader are garbage collected (GC'ed).  A high water mark is used for inducing a GC—when committed memory of all metaspaces reaches this level, a GC is triggered.  You can use the following flag:
-XX:MetaspaceSize=<size>
to specify the initial high water level. 

The interaction between metaspace growth and GC can be summarized as follows:
Metaspaces expand the native memory it is using until it gets to some level (starts at MetaspaceSize). When it hits that level, it does a GC to see if classes can be unloaded. After the GC, it can use freed space in it for metadata. If not enough space has been freed, it uses more native memory.
After the GC it also decides what the next level is for doing a GC to unload classes.  The level mostly increases to have fewer GC's. It sometimes will decrease if lots of space has been freed due to class unloading.  If MetaspaceSize is set higher, then fewer GC will be done early.

Acknowledgement


Some writings here are based on the feedback from Jon Masamitsu. However, the author would assume the full responsibility for the content himself.

References

    1. Java HotSpot VM Options
    2. HotSpot: Monitoring and Tuning Metaspace in JDK 8
    3. Latest JDK 8 and JDK 7 available here
    4. JavaOne Wednesday: Permanent Generation Removal Overview   
    5. jstat Tool: New Metaspace Statistics from -gc Option 
    6. Metatspace in JDK 8 (good) 
    7. VM Class Loading
    8. Learn More About Performance Improvements in JDK 8 

    Tuesday, August 12, 2014

    HotSpot: Monitoring and Tuning Metaspace in JDK 8

    If you upgrade from JDK 7 to JDK 8, there are some changes in JVM that you should pay attention to.  One of them is:
    • The removal of Permanent Generation (PermGen) space.[1]  
    Similar to the Oracle JRockit and IBM JVM's, the JDK 8 HotSpot JVM is now using native memory for the representation of class metadata, which is called Metaspace.  This may have removed the old OOM Error.[2] But ...

    As described in [3], proper monitoring and tuning of the Metaspace is still required in order to limit the frequency or delay of metaspace garbage collections.  In this article, we will show how to achieve that.

    Tuning Metaspace


    When space (either PermGen or Metaspace) is filled up, class need to be unloaded.  In the PermGen era, when PermGen is filled up, a Garbage Collection (or GC) would occur and unload classes.  Without PermGen, we still need to have some way to know when to do a GC to unload classes.  This is when
    -XX:MetaspaceSize=<size>

    comes into play.   When the amount of space used for classes reaching MetaspaceSize, a GC is done to see if there are classes to be unloaded.  If you know that you are going to have lots of classes loaded and use more than 20M (this is the default value for my platform) class data, increasing MetaspaceSize can delay the GC's that are done to check for class unloading.  During your upgrade from JDK 7 to 8, as a first estimate, you can use the old value of PermSize to be your new MetaspaceSize.  You can also read [4] for more details.

    Since Metaspace uses native memory, class metadata allocation theoretically is limited by amount of available native memory (capacity will of course depend if you use a 32-bit JVM vs. 64-bit along with OS virtual memory availability).  However, if you want to limit the amount of native memory used for class metadata, you can set:
    -XX:MaxMetaspaceSize=<size>
    which can restrict the extension of metaspace to the maximum at runtime.

    How Many Classes Are Loaded?


    There are multiple way[6,7] to find out how many classes are loaded and how much space they would take.  Here we introduce one way of finding that information.

    jps is a Java tool that  you can use to  list the instrumented HotSpot Java Virtual Machines (JVMs) on the target system.  For example, here are the list of JVMs that are running on our Linux.

    $ jps -l
    
    32520 weblogic.Server
    8936 weblogic.Server
    11598 weblogic.Server
    32646 weblogic.Server
    7591 weblogic.Server
    27429 weblogic.Server

    To gather class information, you can use jstat tool which displays performance statistics for an instrumented HotSpot Java virtual machine (JVM).  For example, jstat has attached to process 27429 and displayed the statistics on the behavior of the class loader as below:

    $ jstat -class 27429 1000 6
    
    Loaded  Bytes  Unloaded  Bytes     Time
     46167 98340.6      406  1494.6      54.22
     46167 98340.6      406  1494.6      54.22
     46167 98340.6      406  1494.6      54.22
     46167 98340.6      406  1494.6      54.22
     46167 98340.6      406  1494.6      54.22
     46167 98340.6      406  1494.6      54.22


    Class Loader Statistics
    ColumnDescription
    LoadedNumber of classes loaded.
    BytesNumber of Kbytes loaded.
    UnloadedNumber of classes unloaded.
    BytesNumber of Kbytes unloaded.
    TimeTime spent performing class load and unload operations.
      

    From the above output, we know that 46167 classes were loaded and they have taken 96M.  At the time of snapshots, HotSpot has also unloaded 406 classes from which 1.46 M were freed.  Based on this information, you can then decide how to set your MetaspaceSize and MaxMetaspaceSize (not advised) as described above.  However, be warned that once you have set MaxMetaspaceSize, you may still run into OOM error if metaspace cannot be extended further.

    Acknowledgement


    Some writings here are based on the feedback from Jon Masamitsu. However, the author would assume the full responsibility for the content himself.

    References

    1. Java 7 features - PermGen removal
    2. 64-bit java.lang.OutOfMemoryError: PermGen space
    3. Java 8: From PermGen to Metaspace
    4. HotSpot: Understanding Metaspace in JDK 8 
    5. Latest JDK 8 and JDK 7 available here
    6. JavaOne Wednesday: Permanent Generation Removal Overview  
    7. jstat Tool: New Metaspace Statistics from -gc Option 
    8. VM Class Loading
    9. Other JDK 8 articles on Xml and More
    10. Tuning that was great in old JRockit versions might not be so good anymore
      • Trying to bring over each and every tuning option from a JR configuration to an HS one is probably a bad idea.
      • Even when moving between major versions of the same JVM, we usually recommend going back to the default (just pick a collector and heap size) and then redoing any tuning work from scratch (if even necessary).

    Friday, August 1, 2014

    HotSpot: What Does {pd product} Mean?

    In [1], we have discussed how to find out default HotSpot JVM values.  In the output, you may have spotted:
    {pd product}
    What does it mean? In this article, we will examine that in depth.

    Platform Dependent


    {pd product} means platform-dependent product option.  First of all, if a flag is a product option, maybe you want to pay attention to it and may want to change its value for better performance.  If it's an experimental or diagnostic flag, you may want to ignore it.

    If an option is {pd product}, it means that its default value will be dependent on which platform its implementation would be compiled on.  Currently, these platforms are supported, but not limited to:
    • ARM
    • PPC
    • Solaris
    • x86

    Examples


    Two of the {pd product} flags, we would like to discuss here further.  In JDK 7u51,[2] they have the following default values on x86 platforms:

        uintx ReservedCodeCacheSize     = 50331648        {pd product}
        bool  TieredCompilation         = false           {pd product}

    These default values have been changed in later JDK 8 builds.  For example, in JDK 8u20, they have the following default values on the same server:

        uintx ReservedCodeCacheSize     = 251658240        {pd product}
        bool  TieredCompilation         = true             {pd product}

    As discussed in [3,4], you may want to tune these flags for better performance.


    References

    1. What Are the Default HotSpot JVM Values?
    2. Java™ SE Development Kit 7, Update 51 (JDK 7u51)
    3. Performance Tuning with Hotspot VM Option: -XX:+TieredCompilation (XML and More)
    4. A Case Study of Using Tiered Compilation in HotSpot (XML and More)