| type=page | |
| status=published | |
| title=Tuning the Java Runtime System | |
| next=tuning-os.html | |
| prev=tuning-glassfish.html | |
| ~~~~~~ | |
| = Tuning the Java Runtime System | |
| [[GSPTG00006]][[abeia]] | |
| [[tuning-the-java-runtime-system]] | |
| == 4 Tuning the Java Runtime System | |
| The following topics are addressed here: | |
| * link:#abeib[Java Virtual Machine Settings] | |
| * link:#gfpzy[Start Options] | |
| * link:#glaat[Tuning High Availability Persistence] | |
| * link:#abeic[Managing Memory and Garbage Collection] | |
| * link:#abeiq[Further Information] | |
| [[abeib]][[GSPTG00069]][[java-virtual-machine-settings]] | |
| === Java Virtual Machine Settings | |
| Each JDK have own set of JVM options useful for tuning. | |
| The easiest way is to run the following command and then consult the JDK's | |
| documentation to understand all consequences. | |
| [source] | |
| ---- | |
| JAVA_HOME/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | |
| ---- | |
| [[gfpzy]][[GSPTG00070]][[start-options]] | |
| In some situations, performance can be improved by using large page sizes. | |
| For Ultrasparc CMT systems, include the `-XX:+UseLargePages` and | |
| `-XX:LargePageSizeInBytes=256m` arguments with your JVM tuning. | |
| [[glaat]][[GSPTG00071]][[tuning-high-availability-persistence]] | |
| === Tuning High Availability Persistence | |
| If session `s1` and `s2` need to be replicated to an instance (backup | |
| server), the replication module batches the replication messages to be | |
| sent to that instance instead of sending separate replication messages. | |
| This improves performance. In configurations in which a lot of session | |
| replication is performed, you may find better performance by tuning the | |
| `org.shoal.cache.transmitter.max.batch.size` system property. This | |
| property determines the number of replication messages that constitute | |
| one batch. | |
| The default value for this property is `20`. You can try setting it as | |
| high as `90`, depending on system loads. Like all system properties, | |
| this property is set with the `-D` flag in your Java arguments. | |
| [[abeic]][[GSPTG00072]][[managing-memory-and-garbage-collection]] | |
| === Managing Memory and Garbage Collection | |
| The efficiency of any application depends on how well memory and garbage | |
| collection are managed. The following sections provide information on | |
| optimizing memory and allocation functions: | |
| * link:#abeid[Tuning the Garbage Collector] | |
| * link:#abeig[Tracing Garbage Collection] | |
| * link:#abeih[Other Garbage Collector Settings] | |
| * link:#abeii[Tuning the Java Heap] | |
| * link:#abeio[Rebasing DLLs on Windows] | |
| [[abeid]][[GSPTG00205]][[tuning-the-garbage-collector]] | |
| ==== Tuning the Garbage Collector | |
| Garbage collection (GC) reclaims the heap space previously allocated to | |
| objects no longer needed. The process of locating and removing the dead | |
| objects can stall any application and consume as much as 25 percent | |
| throughput. | |
| Almost all Java Runtime Environments come with a generational object | |
| memory system and sophisticated GC algorithms. A generational memory | |
| system divides the heap into a few carefully sized partitions called | |
| generations. The efficiency of a generational memory system is based on | |
| the observation that most of the objects are short lived. As these | |
| objects accumulate, a low memory condition occurs forcing GC to take | |
| place. | |
| The heap space is divided into the old and the new generation. The new | |
| generation includes the new object space (eden), and two survivor | |
| spaces. The JVM allocates new objects in the eden space, and moves | |
| longer lived objects from the new generation to the old generation. | |
| The young generation uses a fast copying garbage collector which employs | |
| two semi-spaces (survivor spaces) in the eden, copying surviving objects | |
| from one survivor space to the second. Objects that survive multiple | |
| young space collections are tenured, meaning they are copied to the | |
| tenured generation. The tenured generation is larger and fills up less | |
| quickly. So, it is garbage collected less frequently; and each | |
| collection takes longer than a young space only collection. Collecting | |
| the tenured space is also referred to as doing a full generation | |
| collection. | |
| The frequent young space collections are quick (a few milliseconds), | |
| while the full generation collection takes a longer (tens of | |
| milliseconds to a few seconds, depending upon the heap size). | |
| Other GC algorithms, such as the Concurrent Mark Sweep (CMS) algorithm, | |
| are incremental. They divide the full GC into several incremental | |
| pieces. This provides a high probability of small pauses. This process | |
| comes with an overhead and is not required for enterprise web | |
| applications. | |
| When the new generation fills up, it triggers a minor collection in | |
| which the surviving objects are moved to the old generation. When the | |
| old generation fills up, it triggers a major collection which involves | |
| the entire object heap. | |
| Both HotSpot and Solaris JDK use thread local object allocation pools | |
| for lock-free, fast, and scalable object allocation. So, custom object | |
| pooling is not often required. Consider pooling only if object | |
| construction cost is high and significantly affects execution profiles. | |
| [[abeie]][[GSPTG00146]][[choosing-the-garbage-collection-algorithm]] | |
| ===== Choosing the Garbage Collection Algorithm | |
| The default collector for Java server class machines will optimize for | |
| throughput but be tolerant of somewhat long pause times. If you would | |
| prefer to have minimal pause times at the expense of some throughput and | |
| increased CPU usage, consider using the CMS collector. | |
| [[gaclx]][[GSPTG00038]][[to-use-the-cms-collector]] | |
| To use the CMS collector | |
| Follow this procedure. | |
| 1. Make sure that the system is not using 100 percent of its CPU. | |
| 2. Configure the CMS collector in the server instance. | |
| + | |
| To do this, add the following JVM options: | |
| * `-XX:+UseConcMarkSweepGC` | |
| * `-XX:SoftRefLRUPolicyMSPerMB=1` | |
| [[abeif]][[GSPTG00147]][[additional-information]] | |
| ===== Additional Information | |
| Use the `jvmstat` utility to monitor HotSpot garbage collection. (See | |
| link:#abeiq[Further Information].) | |
| For detailed information on tuning the garbage collector, see | |
| http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html[Java | |
| SE 6 HotSpot Virtual Machine Garbage Collection Tuning] | |
| (`http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html`). | |
| [[abeig]][[GSPTG00206]][[tracing-garbage-collection]] | |
| ==== Tracing Garbage Collection | |
| The two primary measures of garbage collection performance are | |
| throughput and pauses. Throughput is the percentage of the total time | |
| spent on other activities apart from GC. Pauses are times when an | |
| application appears unresponsive due to GC. | |
| Two other considerations are footprint and promptness. Footprint is the | |
| working size of the JVM process, measured in pages and cache lines. | |
| Promptness is the time between when an object becomes dead, and when the | |
| memory becomes available. This is an important consideration for | |
| distributed systems. | |
| A particular generation size makes a trade-off between these four | |
| metrics. For example, a large young generation likely maximizes | |
| throughput, but at the cost of footprint and promptness. Conversely, | |
| using a small young generation and incremental GC will minimize pauses, | |
| and thus increase promptness, but decrease throughput. | |
| JVM diagnostic output will display information on pauses due to garbage | |
| collection. If you start the server in verbose mode (use the command | |
| `asadmin start-domain --verbose` domain), then the command line argument | |
| `-verbose:gc` prints information for every collection. Here is an | |
| example of output of the information generated with this JVM flag: | |
| [source] | |
| ---- | |
| [GC 50650K->21808K(76868K), 0.0478645 secs] | |
| [GC 51197K->22305K(76868K), 0.0478645 secs] | |
| [GC 52293K->23867K(76868K), 0.0478645 secs] | |
| [Full GC 52970K->1690K(76868K), 0.54789968 secs] | |
| ---- | |
| On each line, the first number is the combined size of live objects | |
| before GC, the second number is the size of live objects after GC, the | |
| number in parenthesis is the total available space, which is the total | |
| heap minus one of the survivor spaces. The final figure is the amount of | |
| time that the GC took. This example shows three minor collections and | |
| one major collection. In the first GC, 50650 KB of objects existed | |
| before collection and 21808 KB of objects after collection. This means | |
| that 28842 KB of objects were dead and collected. The total heap size is | |
| 76868 KB. The collection process required 0.0478645 seconds. | |
| Other useful monitoring options include: | |
| * `-XX:+PrintGCDetails` for more detailed logging information | |
| * `-Xloggc:file` to save the information in a log file | |
| [[abeih]][[GSPTG00207]][[other-garbage-collector-settings]] | |
| ==== Other Garbage Collector Settings | |
| To specify the attributes for the Java virtual machine, use the | |
| Administration Console and set the property under config-name > JVM | |
| settings (JVM options). | |
| [[glgkm]][[GSPTG00148]][[setting-the-maximum-permanent-generation]] | |
| ===== Setting the Maximum Permanent Generation | |
| For applications that do not dynamically generate and load classes, the | |
| size of the permanent generation does not affect GC performance. For | |
| applications that dynamically generate and load classes (for example, | |
| JSP applications), the size of the permanent generation does affect GC | |
| performance, since filling the permanent generation can trigger a Full | |
| GC. Tune the maximum permanent generation with the `-XX:MaxPermSize` | |
| option. | |
| [[glglk]][[GSPTG00149]][[disabling-explicit-garbage-collection]] | |
| ===== Disabling Explicit Garbage Collection | |
| Although applications can explicitly invoke GC with the `System.gc()` | |
| method, doing so is a bad idea since this forces major collections, and | |
| inhibits scalability on large systems. It is best to disable explicit GC | |
| by using the flag `-XX:+DisableExplicitGC`. | |
| [NOTE] | |
| ==== | |
| On Windows systems, setting the `-XX:+DisableExplicitGC` option might | |
| prevent the renaming or removal of open application files. As a result, | |
| deployment, redeployment, or other operations that attempt to rename or | |
| delete files might fail. | |
| Application files can remain open because the files have been used by | |
| class loaders to find classes or resources, or have been opened | |
| explicitly by {productName} or application code but never explicitly | |
| closed. On Windows systems, open files cannot be renamed or deleted. To | |
| overcome this limitation, {productName} uses the `System.gc()` method | |
| to garbage collect the Java object that corresponds to an open file. | |
| When the Java object that corresponds to an open file is garbage | |
| collected, the object's `finalize` method closes the open channel to the | |
| file. {productName} can then delete or rename the file. | |
| ==== | |
| [[glglr]][[GSPTG00150]][[setting-the-frequency-of-full-garbage-collection]] | |
| ===== Setting the Frequency of Full Garbage Collection | |
| {productName} uses RMI in the Administration module for monitoring. | |
| Garbage cannot be collected in RMI-based distributed applications | |
| without occasional local collections, so RMI forces a periodic full | |
| collection. Control the frequency of these collections with the property | |
| `-sun.rmi.dgc.client.gcInterval`. For example, | |
| `- java -Dsun.rmi.dgc.client.gcInterval=3600000` specifies explicit | |
| collection once per hour instead of the default rate of once per minute. | |
| [[abeii]][[GSPTG00208]][[tuning-the-java-heap]] | |
| ==== Tuning the Java Heap | |
| This section discusses topics related to tuning the Java Heap for | |
| performance. | |
| * link:#abeij[Guidelines for Java Heap Sizing] | |
| * link:#abeik[Heap Tuning Parameters] | |
| [[abeij]][[GSPTG00151]][[guidelines-for-java-heap-sizing]] | |
| ===== Guidelines for Java Heap Sizing | |
| Maximum heap size depends on maximum address space per process. The | |
| following table shows the maximum per-process address values for various | |
| platforms: | |
| [[sthref10]][[gacna]] | |
| Table 4-1 Maximum Address Space Per Process | |
| [width="100%",cols="<62%,<38%",options="header",] | |
| |=== | |
| |Operating System |Maximum Address Space Per Process | |
| |Oracle/Redhat/Ubuntu Linux 32-bit |4 GB | |
| |Oracle/Redhat/Ubuntu Linux 64-bit |Terabytes | |
| |Windows XP/2008/7 |2 GB | |
| |Solaris x86 (32-bit) |4 GB | |
| |Solaris 32-bit |4 GB | |
| |Solaris 64-bit |Terabytes | |
| |=== | |
| Maximum heap space is always smaller than maximum address space per | |
| process, because the process also needs space for stack, libraries, and | |
| so on. To determine the maximum heap space that can be allocated, use a | |
| profiling tool to examine the way memory is used. Gauge the maximum | |
| stack space the process uses and the amount of memory taken up libraries | |
| and other memory structures. The difference between the maximum address | |
| space and the total of those values is the amount of memory that can be | |
| allocated to the heap. | |
| You can improve performance by increasing your heap size or using a | |
| different garbage collector. In general, for long-running server | |
| applications, use the Java SE throughput collector on machines with | |
| multiple processors (`-XX:+AggressiveHeap`) and as large a heap as you | |
| can fit in the free memory of your machine. | |
| [[abeik]][[GSPTG00152]][[heap-tuning-parameters]] | |
| ===== Heap Tuning Parameters | |
| You can control the heap size with the following JVM parameters: | |
| * ``-Xms``value | |
| * ``-Xmx``value | |
| * ``-XX:MinHeapFreeRatio=``minimum | |
| * ``-XX:MaxHeapFreeRatio=``maximum | |
| * ``-XX:NewRatio=``ratio | |
| * ``-XX:NewSize=``size | |
| * ``-XX:MaxNewSize=``size | |
| * `-XX:+AggressiveHeap` | |
| The `-Xms` and `-Xmx` parameters define the minimum and maximum heap | |
| sizes, respectively. Since GC occurs when the generations fill up, | |
| throughput is inversely proportional to the amount of the memory | |
| available. By default, the JVM grows or shrinks the heap at each GC to | |
| try to keep the proportion of free space to the living objects at each | |
| collection within a specific range. This range is set as a percentage by | |
| the parameters `-XX:MinHeapFreeRatio=`minimum and | |
| `-XX:MaxHeapFreeRatio=`maximum; and the total size bounded by `-Xms` and | |
| `-Xmx`. | |
| Set the values of `-Xms` and `-Xmx` equal to each other for a fixed heap | |
| size. When the heap grows or shrinks, the JVM must recalculate the old | |
| and new generation sizes to maintain a predefined `NewRatio`. | |
| The `NewSize` and `MaxNewSize` parameters control the new generation's | |
| minimum and maximum size. Regulate the new generation size by setting | |
| these parameters equal. The bigger the younger generation, the less | |
| often minor collections occur. The size of the young generation relative | |
| to the old generation is controlled by `NewRatio`. For example, setting | |
| `-XX:NewRatio=3` means that the ratio between the old and young | |
| generation is 1:3, the combined size of eden and the survivor spaces | |
| will be fourth of the heap. | |
| By default, the {productName} is invoked with the Java HotSpot Server | |
| JVM. The default `NewRatio` for the Server JVM is 2: the old generation | |
| occupies 2/3 of the heap while the new generation occupies 1/3. The | |
| larger new generation can accommodate many more short-lived objects, | |
| decreasing the need for slow major collections. The old generation is | |
| still sufficiently large enough to hold many long-lived objects. | |
| To size the Java heap: | |
| * Decide the total amount of memory you can afford for the JVM. | |
| Accordingly, graph your own performance metric against young generation | |
| sizes to find the best setting. | |
| * Make plenty of memory available to the young generation. The default | |
| is calculated from `NewRatio` and the `-Xmx` setting. | |
| * Larger eden or younger generation spaces increase the spacing between | |
| full GCs. But young space collections could take a proportionally longer | |
| time. In general, keep the eden size between one fourth and one third | |
| the maximum heap size. The old generation must be larger than the new | |
| generation. | |
| For up-to-date defaults, see | |
| http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html[Java | |
| HotSpot VM Options] | |
| (`http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html`). | |
| [[GSPTG00032]][[fxxpw]] | |
| Example 4-1 Heap Configuration on Solaris | |
| This is an exmple heap configuration used by {productName} on Solaris | |
| for large applications: | |
| [source] | |
| ---- | |
| -Xms3584m | |
| -Xmx3584m | |
| -verbose:gc | |
| -Dsun.rmi.dgc.client.gcInterval=3600000 | |
| ---- | |
| [[abeil]][[GSPTG00031]][[survivor-ratio-sizing]] | |
| Survivor Ratio Sizing | |
| The `SurvivorRatio` parameter controls the size of the two survivor | |
| spaces. For example, `-XX:SurvivorRatio=6` sets the ratio between each | |
| survivor space and eden to be 1:6, each survivor space will be one | |
| eighth of the young generation. The default for Solaris is 32. If | |
| survivor spaces are too small, copying collection overflows directly | |
| into the old generation. If survivor spaces are too large, they will be | |
| empty. At each GC, the JVM determines the number of times an object can | |
| be copied before it is tenured, called the tenure threshold. This | |
| threshold is chosen to keep the survivor space half full. | |
| Use the option `-XX:+PrintTenuringDistribution` to show the threshold | |
| and ages of the objects in the new generation. It is useful for | |
| observing the lifetime distribution of an application. | |
| [[abeio]][[GSPTG00209]][[rebasing-dlls-on-windows]] | |
| ==== Rebasing DLLs on Windows | |
| When the JVM initializes, it tries to allocate its heap using the `-Xms` | |
| setting. The base addresses of {productName} DLLs can restrict the | |
| amount of contiguous address space available, causing JVM initialization | |
| to fail. The amount of contiguous address space available for Java | |
| memory varies depending on the base addresses assigned to the DLLs. You | |
| can increase the amount of contiguous address space available by | |
| rebasing the {productName} DLLs. | |
| To prevent load address collisions, set preferred base addresses with | |
| the rebase utilty that comes with Visual Studio and the Platform SDK. | |
| Use the rebase utility to reassign the base addresses of the {productName} DLLs to prevent relocations at load time and increase the | |
| available process memory for the Java heap. | |
| There are a few {productName} DLLs that have non-default base | |
| addresses that can cause collisions. For example: | |
| * The `nspr` libraries have a preferred address of 0x30000000. | |
| * The `icu` libraries have the address of 0x4A?00000. | |
| Move these libraries near the system DLLs (`msvcrt.dll` is at | |
| `0x78000000`) to increase the available maximum contiguous address space | |
| substantially. Since rebasing can be done on any DLL, rebase to the DLLs | |
| after installing the {productName}. | |
| [[gacmt]][[GSPTG00039]][[to-rebase-the-glassfish-servers-dlls]] | |
| ===== To rebase the {productName}'s DLLs | |
| [[sthref11]] | |
| Before You Begin | |
| To perform rebasing, you need: | |
| * Windows 2000 | |
| * Visual Studio and the Microsoft Framework SDK rebase utility | |
| 1. Make as-install\ `bin` the default directory. | |
| + | |
| [source] | |
| ---- | |
| cd as-install\bin | |
| ---- | |
| 2. Enter this command: | |
| + | |
| [source] | |
| ---- | |
| rebase -b 0x6000000 *.dll | |
| ---- | |
| 3. Use the `dependencywalker` utility to make sure the DLLs were | |
| rebased correctly. | |
| + | |
| For more information, see the http://www.dependencywalker.com[Dependency | |
| Walker website] (`http://www.dependencywalker.com`). | |
| 4. Increase the size for the Java heap, and set the JVM Option | |
| accordingly on the JVM Settings page in the Admin Console. | |
| 5. Restart the {productName}. | |
| [[GSPTG00033]][[fxxpz]] | |
| Example 4-2 Heap Configuration on Windows | |
| This is an example heap configuration used by {productName} | |
| for heavy server-centric applications, on Windows, as set in the | |
| `domain.xml` file. | |
| [source,xml] | |
| ---- | |
| <jvm-options> -Xms1400m </jvm-options> | |
| <jvm-options> -Xmx1400m </jvm-options> | |
| ---- | |
| [[sthref12]] | |
| See Also | |
| For more information on rebasing, see | |
| http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tools/tools/rebase.asp[MSDN | |
| documentation for rebase utility] | |
| (`http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tools/tools/rebase.asp`). | |
| [[abeiq]][[GSPTG00073]][[further-information]] | |
| === Further Information | |
| For more information on tuning the JVM, see: | |
| * http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html[ | |
| Java HotSpot VM Options] | |
| (`http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html`) | |
| * http://www.oracle.com/technetwork/java/hotspotfaq-138619.html[ | |
| Frequently Asked Questions About the Java HotSpot Virtual Machine] | |
| (`http://www.oracle.com/technetwork/java/hotspotfaq-138619.html`) | |
| * http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html[ |