http://www.oracle.com/technetwork/java/javase/memleaks-137499.html
3.1 Meaning of OutOfMemoryError
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.
https://www.ibm.com/developerworks/library/j-codetoheap/index.html
Published on February 29, 2012
When you run a Java application by executing java
on the command line or by starting some Java-based middleware, the Java runtime creates an operating-system process — just as if you were running a C-based program. In fact, most JVMs are written largely in C or C++. As an operating-system process, the Java runtime faces the same restrictions on memory as any other process: the addressability provided by the architecture, and the user space provided by the operating system.
The memory addressability provided by the architecture depends on the bit size of the processor — for example, 32 or 64 bits, or 31 bits in the case of the mainframe. The number of bits the process can handle determines the range of memory that the processor is capable of addressing: 32 bits provides an addressable range of 2^32, which is 4,294,967,296 bits, or 4GB. The addressable range for a 64-bit processor is significantly larger: 2^64 is 18,446,744,073,709,551,616, or 16 exabytes.
Some of the addressable range provided by the processor architecture is used by the OS itself for its kernel and (for JVMs written in C or C++) for the C runtime. The amount of memory used by the OS and C runtime depends on the OS being used, but it is usually significant: the default usage by Windows is 2GB. The remaining addressable space — termed the user space — is the memory available to the actual process that's running.
For Java applications, then, the user space is the memory used by the Java process, effectively consisting of two pools: the Java heap(s) and the native (non-Java) heap. The size of the Java heap is controlled by the JVM's Java heap settings: -Xms
and -Xmx
set the minimum and maximum Java heap, respectively. The native heap is the user space left over after the Java heap has been allocated at the maximum size setting. Figure 1 shows an example of what this might look like for a 32-bit Java process:
Figure 1. Example memory layout for a 32-bit Java process
In Figure 1, the OS and C runtime use about 1GB of the 4GB of addressable range, the Java heap uses almost 2GB, and the native heap uses the rest. Note that the JVM itself uses memory — the same way the OS kernel and C runtime do — and that the memory the JVM uses is a subset of the native heap.
Anatomy of a Java object
When your Java code uses the new
operator to create an instance of a Java object, much more data is allocated than you might expect. For example, it might surprise you to know that the size ratio of an int
value to an Integer
object — the smallest object that can hold an int
value — is typically 1:4. The additional overhead is metadata that the JVM uses to describe the Java object, in this case an Integer
.
The amount of object metadata varies by JVM version and vendor, but it typically consists of:
- Class : A pointer to the class information, which describes the object type. In the case of a
java.lang.Integer
object, for example, this is a pointer to thejava.lang.Integer
class. - Flags : A collection of flags that describe the state of the object, including the hash code for the object if it has one, and the shape of the object (that is, whether or not the object is an array).
- Lock : The synchronization information for the object — that is, whether the object is currently synchronized.
The object metadata is then followed by the object data itself, consisting of the fields stored in the object instance. In the case of a java.lang.Integer
object, this is a single int
.
So, when you create an instance of a java.lang.Integer
object when running a 32-bit JVM, the layout of the object might look like Figure 2:
Figure 2. Example layout of a java.lang.Integer
object for a 32-bit Java process
As Figure 2 shows, 128 bits of data are used to store the 32 bits of data in the int
value, because the object metadata uses the rest of those 128 bits.
Anatomy of a Java array object
The shape and structure of an array object, such as an array of int
values, is similar to that of a standard Java object. The primary difference is that the array object has an additional piece of metadata that denotes the array's size. An array object's metadata, then, consists of:
- Class : A pointer to the class information, which describes the object type. In the case of an array of
int
fields, this is a pointer to theint[]
class. - Flags : A collection of flags that describe the state of the object, including the hash code for the object if it has one, and the shape of the object (that is, whether or not the object is an array).
- Lock : The synchronization information for the object — that is, whether the object is currently synchronized.
- Size : The size of the array.
Figure 3 shows an example layout for an int
array object:
Figure 3. Example layout of an int
array object for a 32-bit Java process
In Figure 3, 160 bits of data store the 32 bits of data in the int
value, because the array metadata uses the rest of those 160 bits. For primitives such as byte
, int
, and long
, a single-entry array is more expensive in terms of memory than the corresponding wrapper object (Byte
, Integer
, or Long
) for the single field.
Anatomy of more-complex data structures
Good object-oriented design and programming encourage the use of encapsulation (providing interface classes that control access to data) and delegation (the use of helper objects to carry out tasks). Encapsulation and delegation cause the representation of most data structures to involve multiple objects. A simple example is a java.lang.String
object. The data in a java.lang.String
object is an array of characters that is encapsulated by a java.lang.String
object that manages and controls access to the character array. The layout of a java.lang.String
object for a 32-bit Java process might look like Figure 4:
Figure 4. Example layout of a java.lang.String
object for a 32-bit Java process
As Figure 4 shows, a java.lang.String
object contains — in addition to the standard object metadata — some fields to manage the string data. Typically, these fields are a hash value, a count of the size of the string, the offset into the string data, and an object reference to the character array itself.
This means that to have a string of 8 characters (128 bits of char
data), 256 bits of data are for the character array and 224 bits of data are for the java.lang.String
object that manages it, making a total of 480 bits (60 bytes) to represent 128 bits (16 bytes) of data. This is an overhead ratio of 3.75:1.
In general, the more complex a data structure becomes, the greater its overhead. This is discussed in more detail in the next section.
32-bit and 64-bit Java objects
The sizes and overhead for the objects in the preceding examples apply to a 32-bit Java process. As you know from the Background: Memory usage of a Java process section, a 64-bit processor has a much higher level of memory addressability than a 32-bit processor. With a 64-bit process, the size of some of the data fields in the Java object — specifically, the object metadata and any field that refers to another object — also need to increase to 64 bits. The other data-field types — such as int
, byte
, andlong
— do not change in size. Figure 5 shows the layout for a 64-bit Integer
object and for an int
array:
Figure 5. Example layout of a java.lang.Integer
object and an int
array for a 64-bit Java process
Figure 5 shows that for a 64-bit Integer
object, 224 bits of data are now being used to store the 32 bits used for the int
field — an overhead ratio of 7:1. For a 64-bit single-element int
array, 288 bits of data are used to store the 32-bit int
entry — an overhead of 9:1. The effect of this on real applications is that the Java heap memory usage of an application that previously ran on a 32-bit Java runtime increases dramatically when it's moved to a 64-bit Java runtime. Typically, the increase is on the order of 70 percent of the original heap size. For example, a Java application using 1GB of Java heap with the 32-bit Java runtime will typically use 1.7GB of Java heap with the 64-bit Java runtime.
Note that this memory increase is not limited to the Java heap. The native-heap memory-area usage will also increase, sometimes by as much as 90 percent.
Table 1 shows the field sizes for objects and arrays when an application runs in 32-bit and 64-bit mode:
Table 1. Field sizes in objects for 32-bit and 64-bit Java runtimes
*The size of the object fields and of the data used for the each of the object-metadata entries can be reduced to 32 bits via the Compressed References or Compressed OOPs technologies.
Compressed References and Compressed Ordinary Object Pointers (OOPs)
IBM and Oracle JVMs both provide object-reference compression capabilities via the Compressed References (-Xcompressedrefs
) and Compressed OOPs (-XX:+UseCompressedOops
) options, respectively. Use of these options enables the object fields and the object metadata values to be stored in 32 bits rather than 64 bits. This has the effect of negating the 70 percent Java-heap memory increase when an application is moved from a 32-bit Java runtime to a 64-bit Java runtime. Note that the options have no effect on the memory usage of the native heap; it is still higher with the 64-bit Java runtime than with the 32-bit Java runtime.
Memory usage of Java collections
In most applications, a large amount of data is stored and managed using the standard Java Collections classes provided as part of the core Java API. If memory-footprint optimization is important for your application, it's especially useful to understand the function each collection provides and the associated memory overhead. In general, the higher the level of a collection's functional capabilities, the higher its memory overhead — so using collection types that provide more function than you require will incur unnecessary additional memory overhead.
Some of the commonly used collections are:
With the exception of HashSet
, this list is in decreasing order of both function and memory overhead. (AHashSet
, being a wrapper around a HashMap
object, effectively provides less function than HashMap
whilst being slightly larger.)
java - What are the Xms and Xmx parameters when starting JVMs? - Stack Overflow https://stackoverflow.com/questions/14763079/what-are-the-xms-and-xmx-parameters-when-starting-jvms
What are the Xms and Xmx parameters when starting JVMs?
he flag Xmx
specifies the maximum memory allocation pool for a Java virtual machine (JVM), while Xms
specifies the initial memory allocation pool.
This means that your JVM will be started with Xms
amount of memory and will be able to use a maximum of Xmx
amount of memory. For example, starting a JVM like below will start it with 256 MB of memory and will allow the process to use up to 2048 MB of memory:
java -Xms256m -Xmx2048m
The memory flag can also be specified in multiple sizes, such as kilobytes, megabytes, and so on.
-Xmx1024k
-Xmx512m
-Xmx8g
The Xms
flag has no default value, and Xmx
typically has a default value of 256 MB. A common use for these flags is when you encounter a java.lang.OutOfMemoryError
.
When using these settings, keep in mind that these settings are for the JVM's heap, and that the JVM can/will use more memory than just the size allocated to the heap. From Oracle's documentation:
Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.
-Xmx - http://www.eclipse.org/openj9/docs/xms/
-Xms / -Xmx
These Oracle® Hotspot™ options set the initial/minimum Java™ heap size, and the maximum heap size respectively. These options are recognized by the OpenJ9 VM.
Notes:
- If you set
-Xms
>-Xmx
, the OpenJ9 VM fails with the message-Xms too large for -Xmx
. - If you exceed the limit set by the
-Xmx
option, the OpenJ9 VM generates anOutofMemoryError
.
If you are allocating the Java heap with large pages, see also -Xlp and More effective heap usage using compressed references.
You can also use the -Xmo
option (not supported by the balanced garbage collection policy):
If the scavenger is enabled, -Xms
≥ -Xmn
+ -Xmo
If the scavenger is disabled, -Xms
≥ -Xmo
Syntax
Setting | Effect | Default |
---|---|---|
-Xms<size> |
Set initial heap size | 8 MB |
-Xmx<size> |
Set maximum heap size | 25% of available memory (25 GB maximum) |
See Using -X command-line options for more information about the <size>
parameter.
See Default settings for the OpenJ9 VM for more about default values.
Examples
-Xms2m -Xmx64m
- Heap starts at 2 MB and grows to a maximum of 64 MB.
-Xms100m -Xmx100m
- Heap starts at 100 MB and never grows.
-Xms50m
- Heap starts at 50 MB and grows to the default maximum.
-Xmx256m
- Heap starts at default initial value and grows to a maximum of 256 MB.
-
[root@d ~]# java -X
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
-Xbootclasspath:<directories and zip/jar files separated by :>
set search path for bootstrap classes and resources
-Xbootclasspath/a:<directories and zip/jar files separated by :>
append to end of bootstrap class path
-Xbootclasspath/p:<directories and zip/jar files separated by :>
prepend in front of bootstrap class path
-Xdiag show additional diagnostic messages
-Xnoclassgc disable class garbage collection
-Xincgc enable incremental garbage collection
-Xloggc:<file> log GC status to a file with time stamps
-Xbatch disable background compilation
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-Xprof output cpu profiling data
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions
-Xshare:off do not attempt to use shared class data
-Xshare:auto use shared class data if possible (default)
-Xshare:on require using shared class data, otherwise fail.
-XshowSettings show all settings and continue
-XshowSettings:all
show all settings and continue
-XshowSettings:vm show all vm related settings and continue
-XshowSettings:properties
show all property settings and continue
-XshowSettings:locale
show all locale related settings and continueThe -X options are non-standard and subject to change without notice.
[root@d ~]#