Cross Column

Showing posts with label JVM. Show all posts
Showing posts with label JVM. Show all posts

Sunday, November 23, 2014

G1 GC: Humongous Objects and Humongous Allocations

For Garbage First Garbage Collector (G1 GC), any object that is more than half a region size is considered a Humongous Object.   A humongous object is directly allocated into Humongous Regions.[1]

In this article, we will discuss the following topics:
  • Humongous regions and humongous allocations
  • How humongous allocations impact G1's performance?
  • How to detect humongous allocations?
    • Basic Investigation
    • Advanced Investigation

Humongous Regions and Humongous Allocations


A humongous object is allocated directly in the humongous regions. These humongous regions are a contiguous set of regions. StartsHumongous marks the start of the contiguous set and ContinuesHumongous marks the continuation of the set.

Before allocating any humongous region, the marking threshold is checked, initiating a concurrent cycle, if necessary. Dead humongous objects are freed at the end of the marking cycle during the cleanup phase also during a full garbage collection cycle (but, a new implementation has changed this; see the next section).

Since each individual set of StartsHumongous and ContinuesHumongous regions contains just one humongous object, the space between the end of the humongous object and the end of the last region spanned by the object is unused. For objects that are just slightly larger than a multiple of the heap region size, this unused space can cause the heap to become fragmented.

How Humongous Allocations Impact G1's Performance?


In the old implementation, humongous objects are not released until after a full concurrent marking cycle.[4]  This is far from ideal for many transaction-based enterprise applications that create short-lived (i.e., in the transaction scope) humongous objects such as ResultSet(s) generated from JDBC queries.  This results in the heap filling up relatively quickly and leads to unnecessary marking cycles to reclaim them.

A new implementation since:
java version "1.8.0_40-ea"
Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b05, mixed mode)
handles humongous regions differently and can reclaim them earlier if they are short-lived (see [4] for details).

For investigating humongous allocations in G1, you should begin with the following minimal set of VM options:
  • -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC (-XX:+UseG1GC)

Basic Humongous Allocation Investigation


For basic humongous allocations investigation, you simply add a new option:
  • -XX:+PrintAdaptiveSizePolicy
This option will print out something like below:
12025.832: [G1Ergonomics (Concurrent Cycles) request concurrent cycle initiation, reason: occupancy higher than threshold, occupancy: 3660578816 bytes, allocation request: 1048592 bytes, threshold: 3650722120 bytes (85.00 %), source: concurrent humongous allocation]
From the above, we saw a humongous allocation is initiated with a request size of 1048592 bytes. Note that our region size is 1MBytes in this test. So, the request object is considered as humongous (i.e., 1048592 Bytes > half of 1 MBytes).

In the output, you can also find the following entries:
      [Humongous Reclaim: 0.0 ms]
         [Humongous Total: 54]
         [Humongous Candidate: 0]
         [Humongous Reclaimed: 0]
This shows that there are 54 humongous regions found in this GC event.   Also, none of them were reclaimed in this GC event. The reason is that the current algorithm is relatively conservative and it skips humongous objects for reclamation if there are sparse references into them.  In the case that those references belongs to sparse table entries, G1 may improve the reclamation rate by discovering if they are actually not referenced at all after iterating the table.  A performance enhancement is pending for this effort now.[5]

Advanced Humongous Allocation Investigation


To further investigate humongous allocation in more details, you can add:
-XX:+PrintAdaptiveSizePolicy -XX:+UnlockExperimentalVMOptions -XX:+G1ReclaimDeadHumongousObjectsAtYoungGC -XX:G1LogLevel=finest -XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC
Note that the following VM options are experimental:
  • G1TraceReclaimDeadHumongousObjectsAtYoungGC[4]
  • G1ReclaimDeadHumongousObjectsAtYoungGC[3]
  • G1LogLevel (i.e., [fine|finer|finest])
So, that's why we added the unlock option;
-XX:+UnlockExperimentalVMOptions
With extra printing options, you will find detailed description of humongous allocations as shown below:
3708.669: [SoftReference, 0 refs, 0.0000340 secs]3708.669: [WeakReference, 1023 refs, 0.0001790 secs]3708.669: [FinalReference, 295 refs, 0.0007020 secs]3708.670: [PhantomReference, 0 refs, 0.0000060 secs]3708.670: [JNI Weak Reference, 0.0000140 secs]Live humongous 1 region 9 size 65538 with remset 1 code roots 0 is marked 0 live-other 0 obj array 0

Live humongous 1 region 10 size 88066 with remset 1 code roots 0 is marked 0 live-other 0 obj array 0
Live humongous 1 region 15 size 262146 with remset 1 code roots 0 is marked 0 live-other 0 obj array 1
...
Finally, you can also use Java Flight Recorder (JFR) and Java Mission Control (JMC) to get information about humongous objects by showing their allocation sources with stack traces.[7]

References

  1. Garbage First Garbage Collector Tuning
  2. G1GC: Migration to, Expectations and Advanced Tuning
  3. Thread local allocation buffers (TLAB's)
  4. Early reclamation of large objects in G1
    • Introduced since 8u40 b02 and 8u45
    • Was not back ported to 8u20
  5. Early reclaim of large objects that are referenced by a few objects
  6. G1TraceReclaimDeadHumongousObjectsAtYoungGC
    • JDK-8058801
      • Prints information about live and dead humongous objects
        • (Before bug fix) prints that information when there is at least one humongous candidate.
        • (After bug fix) prints that information even when there is no humongous candidates; it also prints humongous object size in the output
  7. Java Mission Control (JMC) and Java Flight Recorder (JFR)
  8. Garbage-First Garbage Collector (JDK 8 HotSpot Virtual Machine Garbage Collection Tuning Guide)
  9. Other JDK 8 articles on Xml and More
  10. Concurrent Marking in G1

Friday, February 14, 2014

java.lang.ClassCastException: [I cannot be cast to java.util.List.

Caused by: java.lang.ClassCastException: [I cannot be cast to java.util.List.
Initially, I was confused by seeing the sentence "I cannot be cast to..."  However, it turns out that it should be read as:
"[I" cannot be cast to "java.util.List"
In this article, we will look at the class name (i.e., "[I") used in the class file.

What Is "[I"?


"[I" means array of "ints."  If you use jrcmd to generate a heap histogram,[1] you will see the following contents:

--------- Detailed Heap Statistics: ---------
30.0% 65027k   672176     -1k [C
10.2% 22119k   943754     -2k java/lang/String
10.0% 21592k   183036     -3k [Ljava/lang/Object;
 4.7% 10185k   434587     +0k java/util/HashMap$Entry
 4.7% 10114k    27029  -1254k [B
 4.5% 9783k   111539     +0k [Ljava/util/HashMap$Entry;
 1.9% 4075k    34777     +0k java/lang/Class
 1.9% 4058k    86590     +0k java/util/HashMap
 1.6% 3448k   147156     +0k javax/management/ObjectName$Property
 1.2% 2593k    82994     +0k java/util/LinkedHashMap$Entry
 1.1% 2398k    76765     +0k java/util/concurrent/ConcurrentHashMap$Segment
 1.0% 2215k     9311     +0k [I
 0.9% 1975k    18469     +0k [J

Besides "[I", we also find other array's class names:
  • [C
  • [B
  • [J

Array Representation[2]



In Java, arrays are full-fledged objects. Like objects, arrays are always stored on the heap. Also, multi-dimensional arrays are represented as arrays of arrays.

Arrays have a Class instance associated with their class, just like any other object. All arrays of the same dimension and type have the same class. The length of an array (or the lengths of each dimension of a multidimensional array) does not play any role in establishing the array's class. For example, an array of three ints has the same class as an array of three hundred ints. The length of an array is considered part of its instance data.

The name of an array's class has one open square bracket for each dimension plus a letter or string representing the array's type. For example, the class name for an array of ints is "[I". The class name for a three-dimensional array of bytes is "[[[B". The class name for a two-dimensional array of Objects is "[[Ljava.lang.Object".  Read [3] for more details of this naming convention for array classes.

Conclusions


This exception
java.lang.ClassCastException: [I cannot be cast to java.util.List
turned out to be a bug in the application code, which applies a type cast as shown below:

while (iter.hasNext()) 
{ 
  key = iter.next(); 
  val = (List) mEDefToVOAttrsMap.get(key);  <=== this line threw the Exception

The object returned from get() method was created in this way:

iArr = new int[val.size()]; 

This bug was exposed when we switched from JDK 6 to 7 in our tests.  Maybe due to security enforcements or other reasons, JDK 7 provides more runtime checking than JDK 6 does.  Therefore, this hidden bug has been revealed.

To conclude:
The compiler is not backwards compatible[4] because bytecode generated with JDK 7 won't run in Java 1.6 VM (unless compiled with the -target 1.6 flag[5]). But the JVM is backwards compatible, as it can run older bytecodes.

References

  1. Diagnosing OutOfMemoryError or Memory Leaks in JRockit (Xml and More)
  2. Array Representation (The Java Virtual Machine)
  3. The class File Format
  4. Is JDK “upward” or “backward” compatible?
  5. Cross-Compilation Options
  6. Java Products: All About Versions (Xml and More)







Thursday, February 6, 2014

Hotspot: Creating Flight Recording and Viewing Object Allocation

In [1], Marcus has written an excellent article on "Creating Flight Recording." Based on his advice, we have created a JFR recording with object allocations inside/outside TLAB (Thread Local Allocation Buffer) enabled. Then, we installed Java Mission Control (an Eclipse plug-in) on our 64-bit Windows platform and used it to investigate object allocations in the recording.

In this article, we will visit the following topics:
  • Generating JFR recording
  • Downloading and installing Java Mission Control
  • Viewing object allocations using Java Mission Control

Generating JFR Recording


Following Marcus' Time Fixed Recording example, we have used the following command line options:
  • -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=delay=7800s,duration=300s,name=MyRecording,filename=/tmp/myrecording.jfr,settings=default

In our example, we started the recording for 5 minutes after Hotspot has run for 7800 seconds. To configure the recording, you can use either template provided in jre/lib/jfr folder:
  • default.jfc
  • profile.jfc

For our example, we have chosen the default template (note that the settings parameter can also take a path to a template) in which we have enabled the following settings:
<flag name="allocation-profiling-enabled" label="Allocation Profiling">true</flag>

<event path="java/object_alloc_in_new_TLAB">
  <setting name="enabled" control="allocation-profiling-enabled">true</setting>
  <setting name="stackTrace">true</setting>
</event>

<event path="java/object_alloc_outside_TLAB">
  <setting name="enabled" control="allocation-profiling-enabled">true</setting>
  <setting name="stackTrace">true</setting>
</event>

Note that we have saved an original copy of default.jfc before making the changes. After running our benchmark, it has generated a recording file named:
  • myrecording.jfr

Downloading and Installing Java Mission Control



Capability
Oracle JRockit
JDK6 (R28+)
Oracle JDK 7 GA
Oracle JDK
7u40+
Host JRMC/JMC GUI
Yes (JRMC) Yes (JMC) Yes (JMC)
WLDF JFR Events and Analysis
Yes Yes Yes
JFR, JMC Convergence
(JVM Events)
Yes No Yes
                 Table 1  Oracle JDK 7 Java Mission Control Support

You can follow the instructions from [2] to download Java Mission Control—an Eclipse plug-in. However, instead of using https, you should use http as shown above. Also, be noted that
Java Mission Control 5.2.0 does not support Kepler, only Juno.[3,4]
So, you need to download Eclipse Juno from here. If you installed JMC in Eclipse Kepler, you would see the problem as reported in [5].




Viewing object allocations using Java Mission Control


After opening myrecording.jfr, select Memory tab group on the left as shown above.  The Memory tab group shows Information on memory management and garbage collections. It is comprised of these tabs:
  • Overview Tab
  • Garbage Collections Tab
  • GC Times Tab
  • GC Configuration Tab
  • Allocations Tab
  • Object Statistics Tab
The Allocation tab is a good starting point if you suspect that you have problems with object allocation. It contains data about allocated objects and Thread Local Area Buffers (TLABs). This tab has information about how much memory each thread has allocated.

To recap: when we did the recording, we have enabled the following events:
  • java/object_alloc_in_new_TLAB
  • java/object_alloc_outside_TLAB
which are displayed in the above figure:
  • Allocation in new TLAB
  • Allocation outside TLAB


References

  1. Creating Flight Recordings
  2. Oracle Java Mission Control Downloads
  3. Java Mission Control for Eclipse
  4. Oracle® Java Mission Control
    • Oracle® Java Mission Control is a set of plug-ins for Eclipse 3.8 or 4.2.
  5. Mission Control and Flight Recorder on HotSpot JVM
  6. Which JVM?
    • If opening JFR recordings takes forever,  you may need to increase heap size.
  7. JDBC in Java Mission Control 
  8. JDK Mission Control (JMC) 8.1.0 Downloads 

Sunday, December 29, 2013

JRockit: Analyzing GC With JRockit Verbose Output (-Xverbose:memdbg)

Before any JRockit performance tuning, you need to assess the sizes of the objects allocated by your application.[4] One way to access live data size is to view object allocation statistics from the GC log file.

In this article, we will show you how to access object allocation statistics by enabling the JRockit verbose output:
  • -Xverbose:memdbg

Verbose memdbg Log Module[1]


The -Xverbose:memdbg log module is an alias that starts several memory-related log modules to provide a complete picture of the memory management. The memdbg log module sets the memory module to the debug level. This information can also be obtained by setting:
  • -Xverbose:memory=debug

The overhead of the verbose memdbg output is low, which means it can be used in production environments. For example, after enabling -Xverbose:memdb, the overhead has caused the Average Response Time (ART) to deteriorate by 2.25% using our benchmark.

Understanding Verbose Output


After setting the memory module to the debug level, JRockit provides us tons of information. To understand its formats, read [1]. Here we will focus only on OC's (old collections). For example, here is a typical output from the memory log module at the debug level:

[DEBUG][memory ][06310] [OC#41] GC reason: Allocation request failed (1048592 bytes).
[DEBUG][memory ][06310] [OC#41] 2607.371: OC started.
[INFO ][alloc  ][06310] [OC#41] Pending requests at 'Before OC' - Total: 1, TLAs: 0(approx 0 bytes), objects: 1 (1048592 bytes). Max age: 0.
[INFO ][compact][06310] [OC#41] Compaction reason: Normal.
[INFO ][compact][06310] [OC#41] Compacting 128 of 4096 parts at index 384. Compaction type is internal. Exceptional: No.
[INFO ][compact][06310] [OC#41] Compaction area start: 0x8c000000, end: 0x90000000.
Timeout: 411.471 ms.
[INFO ][compact][06310] [OC#41] Compactset limit (per thread): 316839 (dynamic), not using matrixes.
[DEBUG][memory ][06310] [OC#41] Starting parallel marking phase.
[DEBUG][memory ][06310] [OC#41] SemiRef phase WeakJNIHandles run in single threadedmode.
[DEBUG][memory ][06310] [OC#41] SemiRef phase ClassConstraints run in single threaded mode.
[DEBUG][memory ][06310] [OC#41] SemiRef phase FinalMemleak run in single threaded mode.
[DEBUG][memory ][06310] [OC#41] Adding 48 temporary work packets to permanent pool,now 811 packets.
[DEBUG][memory ] [OC#41] Total mark time: 307.204 ms.
[DEBUG][memory ] [OC#41] Ending marking phase.
[DEBUG][memory ] [OC#41] Starting parallel sweeping phase.
[INFO ][nursery] [OC#41] Setting keepAreaMarkers[0] to 0xc9872bc0.
[INFO ][nursery] [OC#41] Setting keepAreaMarkers[1] to 0xcc97f7a0.
[INFO ][nursery] [OC#41] Setting keepAreaMarkers[2] to 0xd20f6088.
[INFO ][nursery] [OC#41] Next keeparea will start at 0xcc97f7a0 and end at 0xd20f6088.
[INFO ][nursery] [OC#41] Nursery size increased from 0KB to 120414KB. Nursery list consists of 2760 parts.
[INFO ][nursery] [OC#41] Average part size: 44KB. Contraharmonic mean (CHM):946KB. CHM per part: 0KB. Normalized CHM: 0.007856.
[DEBUG][memory ][ [OC#41] Total sweep time: 159.954 ms.
[DEBUG][memory ] [OC#41] Ending sweeping phase.
[INFO ][nursery] [OC#41] Nursery size remains at 120414KB. Nursery list consists of 2760 parts.
[INFO ][nursery] [OC#41] Average part size: 44KB. Contraharmonic mean (CHM):946KB. CHM per part: 0KB. Normalized CHM: 0.007856.
[INFO ][alloc  ] [OC#41] Satisfied 0 object and 0 tla allocations. Pending requests went from 1 to 1.
[INFO ][compact] [OC#41] Average compact time ratio (move phase/total time):0.655049.
[INFO ][compact] [OC#41] Compaction time, total: 158.705 ms (target 411.471 ms).
[INFO ][compact] [OC#41] Compaction moved 1295486 objects and left 349 objects. Total moved size 64028976B.
[INFO ][compact] [OC#41] Compaction added 3047752B of free memory in 2 parts.
[INFO ][compact] [OC#41] Compaction time, move phase: 58.023 ms (target 205.735 ms).
[INFO ][compact] [OC#41] Compaction time, update phase: 100.669 ms (target 205.735 ms).
[INFO ][compact] [OC#41] Found 3350566 references. Internal: 1807732  External: 1542834.
[INFO ][compact] [OC#41] Updated 3339159 references. Internal: 1807048  External: 1532111.
[INFO ][alloc  ] [OC#41] Pending requests at 'After OC' - Total: 1, TLAs: 0 (approx 0 bytes), objects: 1 (1048592 bytes). Max age: 1.
[DEBUG][memory ] [OC#41] Page faults before OC: 1, page faults after OC: 1, pages in heap: 524288.
[DEBUG][memory ] [OC#41] Nursery size after OC: 120414KB. (Free: 120371KB Parts: 2760)
[INFO ][memory ] [OC#41] 2607.371-2607.928: OC 1890153KB->1756549KB (2097152KB), 0.558 s, sum of pauses 472.469 ms, longest pause 472.469 ms.

Note that we have used the following JRockit options:
  • -Xverbose:memdbg -Xverbose:gc -Xverbosedecorations=level,module,timestamp,millis,pid

GC Reason


Old collections can be triggered by different events. For example, in the above example, it shows the reason for OC#41 is:
  • Allocation request failed
There are other events can trigger an OC. For example, it can be:
  • GC reason: Artificial, description: Print Heap Summary
  • GC reason: Artificial, description: Print Heap Diagnostics

From our GC log file, we have found the following OC statistics (total: 235)
  • GC reason: Allocation request failed (total: 219)
  • GC reason: Artificial, description: Print Heap Summary (total: 8)
  • GC reason: Artificial, description: Print Heap Diagnostics (total: 8)
Among all events, you can count those artificial heap printing events as the overhead of enabling:
  • -Xverbose:memdbg

References

  1. Understanding Verbose Output
  2. JRockit: A Case Study of Thread Local Area (TLA) Tuning (Xml and More)
  3. JRockit: Thread Local Area Size and Large Objects (Xml and More)
  4. Analyzing the Performance Impact of Memory Utilization and Garbage Collection

Friday, December 27, 2013

JRockit: Thread Local Area Size and Large Objects

Large objects can be a problem for an application. If your Java application allocates a lot of objects, especially large objects, it helps to play around with various Thread Local Area (TLA) settings.[1] For a case study, read [11].

If you try to find the default settings of TLA by using:
  • -XX (an alias for -Xprintflags)
it prints out the following information in JRockit R28.2.5:
        TlaWasteLimit = 0 (default)
                (Alias: -XXlargeObjectLimit)
                - Internal. Use -XXtlaSize:wasteLimit instead.
        TlaMinSize = 0 (default)
                (Alias: -XXminBlockSize)
                - Internal. Use -XXtlaSize:min instead.
        TlaPreferredSize = 0 (default)
                - Internal. Use -XXtlaSize:preferred instead.

Hmm. That is not very helpful. In this article, we will discuss:
  • Thread local area size and large objects
  • How to find out the default TLA settings?

Thread Local Area Size and Large Objects[1-4]


The thread local area (TLA) is a chunk of free space reserved on the heap or the nursery and given to a thread for its exclusive use. A thread can allocate small objects in its own TLA without synchronizing with other threads. When the TLA gets full the thread simply requests a new TLA. The objects allocated in a TLA are accessible to all Java threads and are not considered “thread local” in any way after they have been allocated.

Increasing the TLA size is beneficial for multi-threaded applications where each thread allocates a lot of objects. Increasing the TLA size is also beneficial when the average size of the allocated objects is large, as this allows larger objects to be allocated in the TLAs. Increasing the TLA size too much may however cause more fragmentation and more frequent garbage collections. Before any JRockit performance tuning, you need to assess the sizes of the objects allocated by your application. One way to access live data size is to view object allocation statistics. There are multiple ways of achieving that:
  • You can create a JRockit Flight Recorder recording and view object allocation statistics in the JRockit Flight Recorder[7]
  • You can use the following JVM option:
    • -Xverbose:memdbg Xverbose:gc -Xverbosedecorations=level,module,timestamp,millis,pid

Large Object: Pre-R28 vs. Post-R28[1]


In JRockit versions earlier than R28, large objects were allocated immediately on the heap and never in a TLA. A flag called –XXlargeObjectLimit was provided to tell JRockit the minimum number of bytes an object should be of in order to be treated as "large". The default was 2 KB.

JRockit post R28 uses a waste limit for TLA space instead. This constrains the amount of TLA space that can be thrown away for each TLA when large objects are allocated and is a more flexible solution.

The R28 allocation algorithm now works like this—JRockit tries to allocate every object regardless of its size in the current TLA. If it doesn't fit and the waste limit is less than the space left in the TLA, the object
goes directly on the heap. Otherwise, JRockit will "waste" the rest of this TLA and try to allocate the object in a new TLA or directly on the heap, depending on the size of the object.

The TLA sizes are set using the following option:
  • -XXtlaSize:min=size,preferred=size,wasteLimit=size[8]
    • min
      • Sets the minimum TLA size. 
    • preferred
      • Sets a preferred TLA size.  This means that TLAs will be the preferred size whenever possible, but can be as small as the min size.
    • wasteLimit
      • Sets the waste limit for TLAs. This is the maximum amount of free memory that a TLA is allowed to have when a thread requires a new TLA.
The following relation is true for the TLA size parameters:
  • -XXtlaSize:wasteLimit <= -XXtlaSize:min <= -XXtlaSize:preferred
Read [9] for the tuning advice.

What are the default TLA settings?


To find out the default TLA settings, you can use the following JVM option:[12]
  • -Xverbose:memdbg
For example, here is the output:

[DEBUG][memory ][19709] Minimum TLA size is 2048 bytes.
[DEBUG][memory ][19709] Preferred TLA size is 16384 bytes.
[DEBUG][memory ][1388121278654][19709] TLA waste limit is 2048 bytes.


from the following JVM options:
  • -Xms2g -Xmx2g -Xverbose:memdbg -Xgc:pausetime -Xverbose:gc -Xverbosedecorations=level,module,timestamp,millis,pid

References

  1. Oracle JRockit- The Definitive Guide
  2. Tuning Java Virtual Machines (JVMs)
  3. On Nursery Sizing (Migrated)
    • The goal of nursery sizing to get as much memory as possible freed by young collections rather than old collections.
    • The rule of thumb is that a nursery size of approximately half of the free memory on the heap is nearly optimal.
    • If your application is sensitive to latencies you may want to decrease the nursery size to shorten the young collection pause times.
    • If you're using the garbage collection mode optimizing for short pauses (-Xgcprio:pausetime) or the static generational concurrent garbage collector (-Xgc:gencon) you will most likely want to tune the nursery size manually.
  4. First Steps for Tuning the Oracle JRockit JVM
  5. Oracle® JRockit Diagnostics and Troubleshooting Guide (Release R28)
  6. Oracle® JRockit Performance Tuning Guide (Release R28)
  7. Oracle® JRockit Flight Recorder Run Time Guide (Release R28)
  8. -XXtlaSize Parameters
  9. Optimizing Memory Allocation Performance (Section 4.4 of this pdf)
  10. Oracle® JRockit Command-Line Reference (Release R28)
  11. JRockit: A Case Study of Thread Local Area (TLA) Tuning (Xml and More)
  12. JRockit: Analyzing GC With JRockit Verbose Output (-Xverbose:memdbg)  (Xml and More)
  13. Where did all of these ConstPoolWrapper objects come from?!

Thursday, November 7, 2013

Java Throwable: ClassNotFoundException vs. NoClassDefFoundError

Many times we have confused ourselves with the following two Java Throwable messages:

Although both of them are related to Java Classpath,[7] they are different.[1] In a nutshell, they differ in this way:
  • ClassNotFoundException
    • Thrown when an application tries to load a class at run-time and name was provided during runtime not at compile time
  • NoClassDefFoundError[11,12]
    • When JVM or a ClassLoader instance is not able to find a particular class at runtime which was available during compile time

ClassNotFoundException


ClassNotFoundException is thrown when an application tries to load in a class through its string name using:
  • The forName method in class Class.
  • The findSystemClass method in class ClassLoader .
  • The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found. See How-To section below for solutions.

NoClassDefFoundError


The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found. One way to debug NoClassDefFoundError is going back to the design-time environment. Using an IDE, you might be able to find where the class is coming from at compile time. Then use that as a clue to find why that class cannot be found at runtime. See How-To section for more details.

What Could Go Wrong?


Classpath[7] in Java is path to directory or list of directory which is used by ClassLoaders[3] to find and load class in Java program. If a class cannot be found at runtime, it may be due to:
  • Classloaders are not set up correctly[3]
  • Class is corrupted
    • Java compiler is not backwards compatible. For example, bytecode generated with JDK 7 won't run in Java 1.6 JVM.[2]
  • Jar file could be renamed in the runtime environment
  • Your startup script may have overridden Classpath environment variable
  • You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.

How to Resolve it?


The application that triggered the request to load a class receives a ClassNotFoundException or NoClassDefFoundError if neither the classloader nor any of its ancestors can locate the class.[3] In that case, you can take the following actions:
  • You can use System.getproperty("java.class.path") to get the class path used by your Java application at runtime.[4]
  • Try to run with -classpath option using the classpath you think would work: if it works, then it's a sign that some one is overriding java classpath.
  • Check the permission of your jar files.  Your application may not be able to access them.
  • Enable class loading traces at JVM level. For example, you can specify -verbose:class for both JRockit and HotSpot.[5]
  • If your application is deployed in WebLogic server, read [3] and enable classloader debugging. 
    •  For example, you may want to set:
      • -Dweblogic.utils.classloaders.GenericClassLoader.Verbose=true 
      • -Dweblogic.utils.classloaders.ChangeAwareClassLoader.Verbose=true
    • You can also use Classloader Analysis Tool (http://localhost:port/wls-cat/) which is deployed by default on admin servers of domains in development mode.[6]
    • If your application runs in one environment and not in another,
      • Try adding the CLASSPATH explicitly pointing to your jars in setDomainEnv script 
      • You can also set "EXT_PRE_CLASSPATH=...." or "EXT_POST_CLASSPATH=..." where "..." are your jar files. The setDomainEnv.sh will pick up these and add to CLASSPATH. The above environment variables can be set when you log on or somewhere at the top of setDomainEnv.sh.



References

  1. 3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
  2. Is JDK “upward” or “backward” compatible?
  3. WebLogic's Classloading Framework (Xml and More)
  4. System Properties
  5. -verbose:class Option
  6. Using the new WebLogic Classloader Analysis Tool (CAT)
    • Note that I'm not sure if this is still available in newer WLS releases.
  7. How to Set Classpath for Java on Windows Unix and Linux
    • Main difference between PATH and CLASSPATH is that former is used to locate Java commands while later is used to locate Java class files.
  8. java.lang.UnsatisfiedLinkError: Setting Environment Variable (Xml and More)
  9. Using the Classloader Analysis Tool (CAT)
  10. WebLogic Server (WLS) Support Pattern: Investigating Different Classloading Issues (Doc ID 1572862.1)
  11. If you use JPA 2.1 with WLS 12.1.1 or 12.1.2, then you may see this (because JPA 2.1 only supported starting in 12.1.3):
    • java.lang.NoClassDefFoundError: javax/persistence/StoredProcedureQuery
  12. java.lang.NoClassDefFoundError: sun/io/CharacterEncoding (Xml and More)


Thursday, August 8, 2013

Default Values of JRockit's VM Options

Updated (09/19/2014):

You can also add -XX:+UnlockInternalVMOptions to the command line to access JVM internal flags.

To find out what the JRockit's default VM options are, you type:
  •  jdk-jr/bin/java -XX >JR_defaults.txt
Note that -XX is an alias for -Xprintflags in JRockit.

Default Values


Here are the output from this JRockit version:
  java version "1.6.0_37"
  Java(TM) SE Runtime Environment (build 1.6.0_37-b06)
  Oracle JRockit(R) (build R28.2.5-20-152429-1.6.0_37-20120927-1915-linux-x86_64, compiled mode)


Global:
        UnlockDiagnosticVMOptions = false (default, writeable)
                - Enable processing of flags relating to field diagnostics
        UnlockInternalVMOptions = false (default)
                - Enable processing of internal, unsupported flags
Class:
        FailOverToOldVerifier = true (default, writeable)
                - Fail over to old verifier when split verifier fails
        UseVerifierClassCache = true (default)
                - Try to cache java.lang.Class lookups for old verifier.
        UseClassGC = true (default)
                (Alias: -Xnoclassgc)
                - Allow GC of Java classes
Threads:
        UseThreadPriorities = false (default)
                - Use native thread priorities
        DeferThrSuspendLoopCount = 4000 (default, writeable)
                - Number of iterations in safepoint loop until we try blocking
        SafepointSpinBeforeYield = 2000 (default, writeable)
                - Number of iterations in safepoint loop until we yield instead
                  of pause (MP only)
        UseCompilerSafepoints = true (default)
                - Insert safepoint polls in compiled code
        DeferPollingPageLoopCount = -1 (default)
                - Number of iterations in safepoint loop before arming
                  safepoint poll page
        UseMembarForTransitions = false (default)
                - Use membar to serialize thread states.
        UseNativeLockProfiling = false (default)
                - Profile use of internal JVM monitors
        TrustPThreadStackInfo = false (default)
                - Trust information from pthreads about stack start and size
JNI:
        CheckJNICalls = false (default)
                - Verify all arguments to JNI calls
        AbortOnFailedJNICheck = true (default)
                - Used with CheckJNICalls. If true, abort the JVM upon first
                  JNI parameter error.
        ErrorOnFailedJNICheck = false (default)
                - Used with CheckJNICalls. If true, any errors will be
                  signalled through a java.lang.Error.
JDK:
        UseNewHashFunction = false (default)
                - Use HashMaps new hash function on jdks that does not do so by
                  default
        TreeMapNodeSize = 64 (default)
                - Size of entry array in each java.util.TreeMap node
        MaxDirectMemorySize = 0 (default)
                - Maximum total size of NIO direct-buffer allocations
        UseLazyStackTraces = true (default)
                - Generate stacktraces lazily for thrown Exceptions
        ShowInternalMethodsInStackTrace = false (default, writeable)
                - Show JVM internal code in java stacktraces.
        ExceptionTraceFilter = (null) (default)
                - Pattern that limits what exceptions are logged.
OS:
        ReduceSignalUsage = false (default)
                (Alias: -Xrs)
                - Reduce the use of OS signals in Java and/or the VM
        MaxFDLimit = true (default)
                - Maximize the available number of filedescriptors.
        MaxLargePageSize = 256M (default)
                - Use value as maximum size for large pages (if possible).
GC:
        UseLowAddressForHeap = true (default)
                - Use low 4Gb address space for Java heap if possible.
        UseLargePagesForHeap = false (default)
                - Attempt to use large page translation for the Java heap.
        ForceLargePagesForHeap = false (default)
                - Force the use of large page translation for the Java heap.
        CompressedRefs = false (default)
                (Alias: -XXcompressedRefs)
                - Use 32-bit java references on 64-bit OS - implies a heap
                  maximum of 4Gb (probably less)
        InitialHeapSize = 0 (default)
                (Alias: -Xms)
                - Initial size of Java Object heap
        MaxHeapSize = 0 (default)
                (Alias: -Xmx)
                - Maximum size of Java Object heap
        GCTimeRatio = 19 (default)
                - The ratio of time spent in garbage collection compared to
                  outside of garbage collection.
        GCTimePercentage = 0.000000 (default)
                - The percentage of time spent in garbage collection of total
                  run time.
        GCTrigger = 0 (default)
                (Alias: -XXgcTrigger)
                - The threshold of free heap before a concurrent GC is started
        ForceEarlyOC = true (default)
                - Force an early OC before old space is empty to avoid
                  promotion failed.
        ForceEarlyOCMaxPercentage = 5.000000 (default)
                - Maximum percentage of heap that is allowed to have left
                  before doing an early OC.
        ForceYCOnLargeAllocationFailed = false (default)
                - Force YC on a large allocation failure.
        UseNurseryEvacuation = false (default)
                - Try to evacuate the nursery when a promotion failed has
                  occured.
        DisableEvacuationToNursery = false (default)
                - Disallows evacuation to move objects to where the nursery is.
        NurseryPartsLimit = 10000 (default)
                - The maximum number of nursery parts we will allow before
                  forcing an early OC to fight fragmentation, or 0 for no
                  limit.
        SemiRefPostponedPacketSize = 492 (default)
                - The number of references in a postponed semiref packet.
        SemiRefPrefetchDistance = 0 (default)
                - The number of reference packet indexes to prefetch, or 0 for
                  no prefetch.
        FinalHandleParallelThreshold = -1 (default)
                - The minimum number of final handles needed to process them in
                  parallel.
        FinalHandlePacketSize = 200 (default)
                - The number of handles in a final handle packet.
        MaximumNurseryPercentage = 95 (default)
                - Sets the maximum size of the nursery relative to the amount
                  of free heap after the last old collection.
        AllowYCDuringOC = true (default)
                - Allow young collections during old collections.
        YcAlignAll = false (default)
                - Align all objects (with regards to YcAlignMaxSpill) during YC
        YcAlignMaxSpill = 40 (default)
                - Max spill allowed when aligning objects during YC.
        FullSystemGC = false (default)
                (Alias: -XXfullSystemGC)
                - Always run full GC (with full compaction) when System.gc() is
                  called
        AllowSystemGC = true (default)
                (Alias: -XXnoSystemGC)
                - Run a GC when System.gc() is called
        GcCardTableParts = 1024 (default)
                - Initial number of parts of the card table array
        GcBalancePrefetchDistance = 4 (default)
                - Prefetch distance in a GC balance system workpacket
        GcBalancePacketSize = 493 (default)
                - Packet size of GC balance system workpackets
        NumGenConPrecleaningIterations = 3 (default)
                - Number of precleaning iterations for gencon.
        AllowEmergencyParSweep = true (default)
                - Allow the OC to temporarily change concurrent sweep to
                  parallel if needed.
        UseCfsAdaptedYield = false (default)
                - Use a version of yield adapted for the CFS scheduler. Only
                  for use on CFS.
        TlaWasteLimit = 0 (default)
                (Alias: -XXlargeObjectLimit)
                - Internal. Use -XXtlaSize:wasteLimit instead.
        TlaMinSize = 0 (default)
                (Alias: -XXminBlockSize)
                - Internal. Use -XXtlaSize:min instead.
        TlaPreferredSize = 0 (default)
                - Internal. Use -XXtlaSize:preferred instead.
GC::Compaction:
        UseFullCompaction = false (default)
                - All compactions will be full compactions. Internal. Use
                  -XXcompaction:full instead.
        InternalCompactionPercentage = -1.000000 (default)
                - The percentage of the heap to compact for internal
                  compaction. Internal. Use -XXcompaction:internalPercentage
                  instead.
        ExternalCompactionPercentage = -1.000000 (default)
                - The percentage of the heap to compact for external
                  compaction. Internal. Use -XXcompaction:externalPercentage
                  instead.
        InitialCompactionPercentage = -1.000000 (default)
                - The initial percentage of the heap to compact, for both
                  internal and external compaction. Internal. Use
                  -XXcompaction:initialPercentage instead.
        UseCompaction = true (default)
                - Use compaction to reduce fragmentation. Internal. Use
                  -XXcompaction:enable instead.
        UseAbortableCompaction = false (default)
                - The compactions should be possible to abort. Internal. Use
                  -XXcompaction:abortable instead.
        NumCompactionHeapParts = 4096 (default)
                (Alias: -XXheapParts)
                - The number of heap parts in compaction heuristics. Internal.
                  Use -XXcompaction:heapParts instead.
        InitialExternalReservedHeap = 4M (default)
                - The initial size of the memory reserved by external
                  compaction. Internal. Use
                  -XXcompaction:initialExternalReservedHeap instead.
        UseFixedExternalReservedHeap = false (default)
                - The size of the memory reserved by external compaction is
                  fixed. Internal. Use
                  -XXcompaction:externalReservedHeapIsFixed instead.
        MaxCompactionReferences = 0 (default)
                (Alias: -XXcompactSetLimit)
                - The maximum number of references to store in compaction
                  before skipping. Internal. Use -XXcompaction:maxReferences
                  instead.
        MaxCompactionReferencesPerObject = 0 (default)
                (Alias: -XXcompactSetLimitPerObject)
                - The maximum number of references to store per object in
                  compaction. Internal. Use
                  -XXcompaction:maxReferencesPerObject instead.
        InternalCompactionParts = -1 (default)
                (Alias: -XXinternalCompactRatio)
                - Deprecated. Use -XXcompaction:internalPercentage instead.
        ExternalCompactionParts = -1 (default)
                (Alias: -XXexternalCompactRatio)
                - Deprecated. Use -XXcompaction:externalPercentage instead.
Object allocation:
        UseAllocPrefetch = true (default)
                - Use prefetch on object allocation
        RedoAllocPrefetch = true (default)
                - Do prefetch on object allocation from start of the allocated
                  object
        AllocPrefetchLineLength = -1 (default)
                - Line length for allocation prefetch
        AllocPrefetchDistance = -1 (default)
                - Distance for allocation prefetch
        AllocChunkSize = -1 (default)
                - Size of chunks to clear/prefetch
Javalock:
        UseLockProfiling = false (default)
                - Enable Java lock profiling.
        ThinLockContendedSpinCount = -1 (default)
                - Number of spins between each poll when acquiring a thin lock
        ThinLockContendedPollCount = -1 (default)
                - Number of polls between each short nap when acquiring a thin
                  lock
        ThinLockConvertToFatThreshold = -1 (default)
                - Number of of short naps before converting thin lock to fat
        FatLockContendedSpinCount = -1 (default)
                - Number of spins between each poll when acquiring a fat lock
        FatLockContendedPollCount = -1 (default)
                - Number of polls between each short nap when acquiring a fat
                  lock
        MonitorContendedSpinCount = -1 (default)
                - Number of spins between each poll when acquiring a monitor
                  lock
        MonitorContendedPollCount = -1 (default)
                - Number of polls between each short nap when acquiring a
                  monitor lock
        UseFatLockDeflation = true (default)
                - Try to deflate fat locks to thin
        FatLockDeflationThreshold = 50 (default)
                - Number of uncontended entries on lock before deflation occurs
        UseLockQueueLength = true (default)
                - Make threads go to sleep if contention exceeds # cpus
        UseFatSpin = true (default)
                (Alias: -XXdisableFatSpin)
                - Should we spin-try then acquiring a fat lock
        UseAdaptiveFatSpin = false (default)
                - Should we use adaptive spinning acquiring a fat lock
        UseThreadContentionMonitoring = true (default)
                - Allow thread contention monitoring
JavaLock::LazyUnlocking:
        UseLazyUnlocking = true (default)
                (Alias: -XXlazyUnlocking)
                - Enable lazy unlocking
        UseLazyUnlockingInJIT = true (default)
                - Use lazy locks in JIT code
        UseLazyUnlockingClassBan = true (default)
                - Use class banning
        UseLazyUnlockingTransferClassBan = true (default)
                - Use transfer class banning
JFR:
        FlightRecorder = true (default)
                - Enable flightrecorder
        FlightRecorderOptions = (null) (default)
                - Flight recorder arguments
        StartFlightRecording = (null) (default)
                - Start a Flight recording with args. Equivalent to using
                  "start_flightrecording".
Code memory:
        CodeBlockAbsorbtionSize = 32 (default)
                - Maximum extra size allowed for fitting code memory chunks
        FreeEmptyCodeBlocks = true (default)
                - Free unused code memory
        UseLargePagesForCode = false (default)
                - Attempt to use large page translation compiled code.
        MaxCodeMemory = 0 (default)
                - Maximum amount of memory used for generated code
        ReserveCodeMemory = true (default)
                - Reserve all memory for code at startup
        UseCodeGC = true (default)
                - Allow GC of discarded compiled code
        CodeGCThreshold = 0 (default)
                - Released byte threshold for initiating a code GC
        CodeGCReclaimThreshold = 0 (default)
                - Released byte threshold before compiler attempts to reclaim
                  unused code space
        CodeGCUseReclaim = true (default)
                - Should Code GC attempt reclamation of unused code memory
        CodeGCTaskInterval = 5 (default)
                - Interval in secs between background scans for unused code
                  blocks
Compiler broker:
        MaxOptQueueLength = 0 (default)
                - Maximum allowed optimization queue length before JIT thread
                  helps generate code
        OptThreads = 1 (default)
                - Number of background optimization threads
        JITThreads = 1 (default)
                - Number of background JIT threads
        JITThreadPrio = 5 (default)
                - Priority of background JIT threads
        OptThreadPrio = 5 (default)
                - Priority of background optimization threads
        DisableOptsAfter = -1 (default)
                (Alias: -Xnoopt)
                - Disable optimizations after n seconds
Compiler:
        PreOpt = false (default)
                - Optimize all code on jit (first generation)
        UseCallProfiling = false (default)
                - Use call profiling on unoptimized code
        StrictFP = false (default)
                (Alias: -Xstrictfp)
                - Force strict FP for all methods
        CheckStacks = false (default)
                (Alias: -Xcheckedstacks)
                - Do explicit checks for stack overflow
        DevirtualizeAlways = false (default)
                - Forces devirtualization in jitted code
        UseStringCache = false (default)
                - Cache common arrays used in String constructor
        MethodCodeAlignment = 32 (default)
                - Byte alignment for start of method code
        UseInlineObjectAlloc = true (default)
                - Generate inlined object allocation code.
        UseSafeTimer = false (default)
                - Use fast, signal based timer for System.currentTimeMillis.
        UseOldLockMatching = false (default)
                - Compatibility mode lock matching
JVMTI:
        JavaDebug = false (default)
                (Alias: -Xdebug)
                - Enable java debugging
Management:
        DisableAttachMechanism = false (default)
                - Disable mechanism that allows tools to attach to this VM
        CrashOnOutOfMemoryError = false (default, writeable)
                - Crash JVM process on OutOfMemory
        ExitOnOutOfMemoryError = false (default, writeable)
                - Terminate JVM process on OutOfMemory
        ExitOnOutOfMemoryErrorExitCode = 51 (default, writeable)
                - Exit code for termination of  JVM process on OutOfMemory
        HeapDiagnosticsOnOutOfMemoryError = false (default, writeable)
                - Print Java heap diagnostics on OutOfMemory
        HeapDiagnosticsPath = (null) (default, writeable)
                - When HeapDiagnosticsOnOutOfMemoryError is on, the path
                  (filename or directory) of the dump file (defaults to
                  jrockit_.oomdiag in the working directory)
        HeapDumpOnOutOfMemoryError = false (default, writeable)
                - Dump Java heap to a hprof binary format file on OutOfMemory
        HeapDumpOnCtrlBreak = false (default)
                - Dump heap to file in Ctrl-Break handler
        HeapDumpPath = (null) (default, writeable)
                - When HeapDumpOnOutOfMemoryError is on, the path (filename or
                  directory) of the dump file (defaults to jrockit_.hprof
                  in the working directory)
        SegmentedHeapDumpThreshold = 2G (default, writeable)
                - Generate a segmented heap dump (JAVA PROFILE 1.0.2 format)
                  when the heap usage is larger than this
        HeapDumpSegmentSize = 1G (default)
                - Approximate segment size when generating a segmented heap
                  dump
        StartMemleakOnPort = 0 (default, writeable)
                (Alias: -XXmemleak)
                - Listen for memleak connections on this port (0 for default)
        FlightRecordingDumpOnUnhandledException = false (default, writeable)
                - Generate a Flight Recording dump when a thread is terminated
                  due to an unhandled exception
        FlightRecordingDumpPath = (null) (default, writeable)
                - When FlightRecordingDumpOnUnhandledException is on, the path
                  (filename or directory) of the dump file (defaults to
                  jrockit__.jfr in the working directory)
Runtime:
        AbortOnCrash = false (default, writeable)
                - Abort the JVM in case of an crash.
        DumpOnCrash = true (default, writeable)
                - Generate a dump of the JVM state in case of a crash.
        CoreOnCrash = true (default, writeable)
                - Generate a core dump file of the JVM state in case of a
                  crash.
        WaitOnCrash = false (default, writeable)
                - Wait for user debugger attach in case of a crash.
        AbortOnAssert = true (default, writeable)
                - Abort JVM on assertion
        CrashOnAssert = false (default, writeable)
                - Crash dump the JVM on assertion
        WaitOnAssert = false (default, writeable)
                - Spin and wait JVM on assertion
        NumaMemoryPolicy = (null) (default)
                - Numa memory policy (interleave, preferredlocal, strictlocal)
        BindToNumaNodes = (null) (default)
                - Bind process to Numa nodes
        BindToCPUs = (null) (default)
                - Bind process to CPUs
        UseFastTime = true (default)
                - Force/disable usage of hardware platform support for fast
                  time
        UseJNIPinning = true (default)
                - Use pinning for Objects in call to GetPrimitiveArrayCritical
                  etc

See Also

Friday, March 8, 2013

JRockit: Unable to open temporary file /mnt/hugepages/jrock8SadIG

After system maintenance, our JRockit failed to create the Java virtual machine because it could not acquire the large pages as shown below:

$ bin/java -Xms2560m -Xmx2560m -XlargePages -Xgc:genpar -XlargePages:exitOnFailure -version
[ERROR][osal   ] Unable to open temporary file /mnt/hugepages/jrock8SadIG
[ERROR][memory ] Could not acquire large pages for Java heap.
[ERROR][memory ] Could not setup java heap.
Could not create the Java virtual machine.

In this article, we will discuss how to investigate and resolve this issue.

What to Check?


When using JRockit we have to make a hugetblfs file system available in the directory /mnt/hugepages. Since the message says that it cannot open temporary file /mnt/hugepages/jrock8SadIG, the first thing to check is if that directory was mounted (note that it was mounted before system maintenance).

$ mount -l
nodev on /mnt/hugepages type hugetlbfs (rw)

As shown above, /mnt/hugepages directory was mounted.  The next thing to check is why JRockit cannot open temporary file in that directory.  Could it be privilege?

As described in [1], to make the /mnt/hugepages directory accessible for the oracle user, you need to do:
  • chmod -R 777 /mnt/hugepages

It turns out that it was the culprit.  After issuing the above command, JRockit was able to create Java virtual machine.

References

  1. Tune the JVM that runs Coherence
  2. JRockit: Could not acquire large pages for 2Mbytes code
  3. How to Test Large Page Support on Your Linux System
  4. Understanding Application Memory Performance - Red Hat

Wednesday, September 12, 2012

A Case Study of Using Tiered Compilation in HotSpot

Hotspot has two JITs named c1 (i.e., client JIT) and c2 (i.e., server JIT).[1] The client JIT starts fast but provides less optimizations. So, it is used for GUI application. The server JIT starts more slowly but provide very good optimizations. The idea of tiered compilation [2]is to get the best of both compilers, first JITs the code with c1 and then if the code is really hot to recompile it with c2.

The tiered server runtime is enabled with the following Hotspot VM options:
  • -server -XX:+TieredCompilation
In this article, we show a case study of using HotSpot (build 23.0-b18, mixed mode) with TieredCompilation off/on.

Comparison

You can tune JVM's performance by tuning either memory management or code generaion.  Here we have tuned code generator by turning tiered compilation mode on.  With tiered compilation on, more classes are compiled (or compiled more efficiently) and so they execute faster (i.e., +15%).

Using ATG CRM Demo benchmark, we saw the following KPI changes:



-XX:-TieredCompilation

-XX:+TieredCompilation

% Change

Total Footprint

4431MB

4686MB

-5.4%

Application Server CPU

23%

20%

+15%

Average Response Time

0.234

0.217

+7.8%

Notes


  1. Here is our setting for ReservedCodeCacheSize[2]:
    -TieredCompilation: 128MB
    +TieredCompilation: 256MB
  2. When we turned on tiered compilation mode, we also reserve larger code cache for it (i.e., 256 MB vs. 128 MB).  Code cache is allocated out of native memory (vs. heap).  Total footprint shown in the table includes native memory.  So, we see total footprint is larger when tiered compilation mode is turned on.

References

  1. HotSpot Glossary of Terms
  2. Performance Tuning with Hotspot VM Option: -XX:+TieredCompilation (Xml and More)

Friday, August 31, 2012

Which JVM?

When you report java.lang.OutOfMemoryError: Java heap space, you need to tell people which JVM has thrown the exception.  Sometimes this can be obvious and sometimes it isn't (see below).

An OutOfMemoryError does not necessarily imply a memory leak. The issue might simply be a configuration issue, for example if the specified heap size (or the default size if not specified) is insufficient for the application[1].  In that case, you need to figure out which configuration file to modify.

jps Command

You can use jps (Java Virtual Machine Process Status Tool) to list all local VM identifiers of instrumented HotSpot Java Virtual Machines (JVMs) on the target Linux system.  For example, on my system, it lists:

$ jps 
17291 Server
17468 Jps
7883 Launcher

This list includes one Integrated WebLogic Server (i.e., Server) and one JDeveloper (i.e., Launcher). Note that JDeveloper and Integrated WLS use their own JVM's. So, if you're running Integrated WLS from JDeveloper, you need to know which JVM has thrown the OutOfMemoryError exception.

Configuration Files


Each application uses its own configuration file to start its JVM and you need to know where to find it.

For example, to change heap space sizes, you can modify those parameters in:
  • JDeveloper
    • $JDEV_HOME/jdev/bin/jdev.conf
    • or 'which jdev' and find its containing directory; jdev.conf should be located in the same directory 
    • Note that jdev.conf includes ide.conf which contains the following configurations:
      • AddVMOption  -Xmx640M
      • AddVMOption  -Xms128M
  • WebLogic Server
    • You have two options:
      • Modify MEM_ARGS in the setDomainEnv.sh
      • $setenv USER_MEM_ARGS "-Xms512m -Xmx1024m -XX:MaxPermSize=1024m -XX:CompileThreshold=8000"
        • This will override the settings from WLS scripts as shown below:
          • if [ "${USER_MEM_ARGS}" != "" ] ; then
            MEM_ARGS="${USER_MEM_ARGS}"
            export MEM_ARGS
            fi
    • If this is Integrated WLS, your script folder is located under:
      • ../system11.1.1.6.38.61.92/DefaultDomain/bin
      • On JDev 12c, the heap size is set by the following line (which is embedded in setStartupEnv.sh):[5]
        • set SERVER_MEM_ARGS_64=-Xms1024m -Xmx3072m
          • You can trace the settings starting from startWebLogic.sh, to setDomainEnv.sh, to setSOADomainEnv.sh, and finally to setStartupEnv.sh.
  • Eclipse
    • /eclipse.ini

Project Properties


Here is another case which requires the change of project properties in JDeveloper:
  • Scenario:
    • JDeveloper is used to deploy "server-setup-seed-deploy-test" target with "Run Ant Target" and it threw "java.lang.OutOfMemoryError: PermGen space" exception.[2]
  • Solution:
    • In Jdev window, right click the project file >  Project Properties > Ant > Process > Java Options:
      • -Xms512m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=1024m
    • Note that a new JVM is launched for the Ant process and it uses the above settings.


References

Monday, July 23, 2012

Troubleshooting System Crashes in WebLogic Server

In this article, we will describe how to troubleshoot system crashes in WebLogic Server step by step:
  1. Enabling core dump if it's not done yet
  2. Determining where the crash occurred

Enabling Core Dump

In my test, a fatal error has been detected by the Java Runtime Environment and it tried to write core dump.  However, it cannot:

# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again


You can find above message in the server log file (in <domain loc>/logs). In most Linux Distributions core file creation is disabled by default for a normal user. To enable writing core files you use the ulimit command, it controls the resources available to a process started by the shell. For example, I've added the following line at the top of my start script:

#!/bin/ksh
ulimit -c unlimited


Determining Where the Crash Occurred

Basically a hs_err files is what you get when something goes wrong during a local Java session. Local as in using a Java Virtual Machine (JVM) locally. The HotSpot VM is the default JVM for the Java SE plattform. Hence the name of hs_err files: HotSpot Error log. For example, I have found this file in the WLS domain folder:
  • hs_err_pid18181.log
The error log is a text file consisting of the following sections:
  • A header that provides a brief description of the crash
  • A section with thread information
  • A section with process information
  • A section with system information

It contains information obtained at the time of the fatal error.  For detailed descriptions of the above sections, read [4].

A Case Study

From the error log header, you can tell what the problematic frame is.  For example, this is what I have seen in the error log:

# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/HXXXXX/workspace/jdk7u4-2-build-linux-amd64-product/jdk7u4/hotspot/src/share/vm/oops/methodOop.cpp:498), pid=19941, tid=1098848576
#  assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass())) failed: invalid exception class
#
# JRE version: 7.0_04-bXX
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.0-b21-fastdebug mixed mode linux-amd64 compressed oops)
# Core dump written. Default location: /data/ATG/MXXXXX/user_projects/domains/atgdomain/core or core.19941
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#


---------------  T H R E A D  ---------------

Current thread (0x00002aaac0871000):  JavaThread "[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon [_thread_in_vm, id=19995, stack(0x00000000416f1000,0x00000000417f2000)]

Stack: [0x00000000416f1000,0x00000000417f2000],  sp=0x00000000417ed4d0,  free space=1009k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xc6f6d2]  VMError::report_and_die()+0x2f2
V  [libjvm.so+0x5dfa44]  report_vm_error(char const*, int, char const*, char const*)+0x84
V  [libjvm.so+0x9fd8c8]  methodOopDesc::resolved_checked_exceptions_impl(methodOopDesc*, Thread*)+0x1c8
V  [libjvm.so+0xb14eb4]  Reflection::get_exception_types(methodHandle, Thread*)+0x24
V  [libjvm.so+0xb19741]  Reflection::new_constructor(methodHandle, Thread*)+0x161
V  [libjvm.so+0x8524f6]  JVM_GetClassDeclaredConstructors+0x626
J  java.lang.Class.getDeclaredConstructors0(Z)[Ljava/lang/reflect/Constructor;

In this case, an Internal Error occurred with a thread executing in the library libjvm.so. From the Thread section , we know a JavaThread fails while in the _thread_in_vm state (meaning that it is executing in Java VM code).

Thread Information[2]

The first part of the thread section shows the thread that provoked the fatal error, as follows.
Current thread (0x00002aaac0871000):  JavaThread "[AC...]" [_thread_in_native, id=21139]
                    |                   |         |            |                +-- ID
                    |                   |         |            +---------------- state
                    |                   |         +------------------------------ name
                    |                   +---------------------------------------- type
                    +--------------------------------------------------------- pointer

The thread pointer is the pointer to the Java VM internal thread structure. It is generally of no interest unless you are debugging a live Java VM or core file. The following list shows possible thread types.
  • JavaThread
  • VMThread
  • CompilerThread
  • GCTaskThread
  • WatcherThread
  • ConcurrentMarkSweepThread
The following table shows the important thread states.

Thread State

Description
_thread_uninitialized
Thread is not created. This occurs only in the case of memory corruption.
_thread_new
Thread has been created but it has not yet started.
_thread_in_native
Thread is running native code. The error is probably a bug in native code.
_thread_in_vm
Thread is running VM code.
_thread_in_Java
Thread is running either interpreted or compiled Java code.
_thread_blocked
Thread is blocked.
..._trans
If any of the above states is followed by the string _trans, that means that the thread is changing to a different state.

The thread ID in the output is the native thread identifier. If a Java thread is a daemon thread, then the string daemon is printed before the thread state.

References

  1. Troubleshooting System Crashes
  2. Thread Information
  3. Description of Java hs_err error log files
  4. Description of Fatal Error Log
  5. Monitoring WebLogic Server Thread Pool at Runtime
  6. Understanding JVM Thread States
  7. Understanding WebLogic Incident and the Diagnostic Framework behind It

© Travel for Life Guide. All Rights Reserved.

Analytical Insights on Health, Culture, and Security.