One common indication of a memory leak is the java.lang.OutOfMemoryError error. This error is thrown when there is insufficient space to allocate an object in the Java heap or in a particular area of the heap. The garbage collector cannot make any further space available to accommodate a new object, and the heap cannot be expanded further.
When the java.lang.OutOfMemoryError error is thrown, a stack trace is printed also.
A java.lang.OutOfMemoryError can also be thrown by native library code when a native allocation cannot be satisfied, for example, if swap space is low.
An early step to diagnose an OutOfMemoryError is to determine what the error means. Does it mean that the Java heap is full, or does it mean that the native heap is full? To help you answer this question, the following subsections explain some of the possible error messages, with reference to the detail part of the message:
■ Exception in thread"main": java.lang.OutOfMemoryError: Java heap space See“3.1.1 Detail Message: Java heap space” on page 74.
■ Exception in thread"main": java.lang.OutOfMemoryError: PermGen space See“3.1.2 Detail Message: PermGen space” on page 74.
3
C H A P T E R 3
■ Exception in thread"main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit
See“3.1.3 Detail Message: Requested array size exceeds VM limit” on page 75.
■ Exception in thread"main": java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
See“3.1.4 Detail Message: request <size> bytes for <reason>. Out of swap space?”
on page 75.
■ Exception in thread"main": java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)
See“3.1.5 Detail Message: <reason> <stack trace> (Native method)” on page 76.
3.1.1 Detail Message: Java heap space
The detail message Java heap space indicates that an object could not be allocated in the Java heap. This error does not necessarily imply a memory leak. The problem can be as simple as a configuration issue, where the specified heap size (or the default size, if not specified) is insufficient for the application.
In other cases, and in particular for a long-lived application, the message might be an indication that the application is unintentionally holding references to objects, and this prevents the objects from being garbage collected. This is the Java language equivalent of a memory leak.
Note that APIs that are called by an application could also be unintentionally holding object references.
One other potential source of OutOfMemoryError arises with applications that make excessive use of finalizers. If a class has a finalize method, then objects of that type do not have their space reclaimed at garbage collection time. Instead, after garbage collection the objects are queued for finalization, which occurs at a later time. In the Sun implementation, finalizers are executed by a daemon thread that services the finalization queue. If the finalizer thread cannot keep up with the finalization queue, then the Java heap could fill up and OutOfMemoryError would be thrown.
One scenario that can cause this situation is when an application creates high-priority threads that cause the finalization queue to increase at a rate that is faster than the rate at which the finalizer thread is servicing that queue. Section“3.3.6 Monitoring the Number of Objects Pending Finalization” on page 80discusses how to monitor objects for which finalization is pending.
3.1.2 Detail Message: PermGen space
The detail message PermGen space indicates that the permanent generation is full. The permanent generation is the area of the heap where class and method objects are stored. If an application loads a very large number of classes, then the size of the permanent generation might need to be increased using the -XX:MaxPermSize option.
3.1 Meaning of OutOfMemoryError
Interned java.lang.String objects are also stored in the permanent generation. The java.lang.Stringclass maintains a pool of strings. When the intern method is invoked, the method checks the pool to see if an equal string is already in the pool. If there is, then the intern method returns it; otherwise it adds the string to the pool. In more precise terms, the
java.lang.String.internmethod is used to obtain the canonical representation of the string;
the result is a reference to the same class instance that would be returned if that string appeared as a literal. If an application interns a huge number of strings, the permanent generation might need to be increased from its default setting.
When this kind of error occurs, the text String.intern or ClassLoader.defineClass might appear near the top of the stack trace that is printed.
The jmap -permgen command prints statistics for the objects in the permanent generation, including information about internalized String instances. See“2.7.4 Getting Information on the Permanent Generation” on page 50.
3.1.3 Detail Message: Requested array size exceeds VM limit
The detail message Requested array size exceeds VM limit indicates that the application (or APIs used by that application) attempted to allocate an array that is larger than the heap size.
For example, if an application attempts to allocate an array of 512MB but the maximum heap size is 256MB then OutOfMemoryError will be thrown with the reason Requested array size exceeds VM limit. In most cases the problem is either a configuration issue (heap size too small), or a bug that results in an application attempting to create a huge array, for example, when the number of elements in the array are computed using an algorithm that computes an incorrect size.
3.1.4 Detail Message: request <size> bytes for
<reason>. Out of swap space?
The detail message request <size> bytes for <reason>. Out of swap space? appears to be an OutOfMemoryError. However, the HotSpot VM code reports this apparent exception when an allocation from the native heap failed and the native heap might be close to exhaustion. The message indicates the size (in bytes) of the request that failed and the reason for the memory request. In most cases the <reason> part of the message is the name of a source module reporting the allocation failure, although in some cases it indicates a reason.
When this error message is thrown, the VM invokes the fatal error handling mechanism, that is, it generates a fatal error log file, which contains useful information about the thread, process, and system at the time of the crash. In the case of native heap exhaustion, the heap memory and memory map information in the log can be useful. SeeAppendix C, “Fatal Error Log,”for detailed information about this file.
If this type of OutOfMemoryError is thrown, you might need to use troubleshooting utilities on the operating system to diagnose the issue further. See“2.16 Operating-System-Specific Tools”
on page 64.
The problem might not be related to the application, for example:
■ The operating system is configured with insufficient swap space.
■ Another process on the system is consuming all memory resources.
If neither of the above issues is the cause, then it is possible that the application failed due to a native leak, for example, if application or library code is continuously allocating memory but is not releasing it to the operating system.
3.1.5 Detail Message: <reason> <stack trace> (Native method)
If the detail part of the error message is <reason> <stack trace> (Native method) and a stack trace is printed in which the top frame is a native method, then this is an indication that a native method has encountered an allocation failure. The difference between this and the previous message is that the allocation failure was detected in a JNI or native method rather than in Java VM code.
If this type of OutOfMemoryError is thrown, you might need to use utilities on the operating system to further diagnose the issue. See“2.16 Operating-System-Specific Tools” on page 64.