When you upgrade JDK, you should re-examine all JVM options you have set in your Java applications. For example, let's look at thread stack size tuning specifically. As suggested in [1], it states:
When a new thread is launched, the Java virtual machine creates a new Java stack for the thread. As mentioned earlier, a Java stack stores a thread's state in discrete frames.[3] The Java virtual machine only performs two operations directly on Java Stacks: it pushes and pops frames.
The default thread stack size varies with JVM, OS and environment variables. To find out what your default ThreadStackSize is on your platform, use:[1]
In JDK 8, every time the JVM creates a thread, the OS allocates some native memory to hold that thread’s stack, committing more memory to the process until the thread exits. Thread stacks are fully allocated (i.e., committed, not just reserved) when they are created.
This means that if your application spawns a lot of threads, this can consume a significant amount of memory which could otherwise be used by your application or OS (or it can eventually leads to OutOfMemoryError).
You can reduce your stack size by running with the -Xss option. For example:
In JDK 8, HotSpot installation comes with a feature named Native Memory Tracking (default: disabled). To enable it, use:
After enabling NMT, you can examine the memory footprint taken by either Thread or Thread Stack using:
For example, on a 64-bit Linux platform, here is the thread stack size before and after setting
[0x0000000040049000 - 0x000000004014a000] reserved and committed 1028KB for Thread Stack from
[0x00002aec741ca5e4] JavaThread::run()+0x24
[0x00002aec74083268] java_start(Thread*)+0x108
[0x0000000040078000 - 0x00000000400b9000] reserved and committed 260KB for Thread Stack from
[0x00002b02c69156e4] JavaThread::run()+0x24
[0x00002b02c67ce338] java_start(Thread*)+0x108
The thread stack is used to push stacks frames in nested method calls. If the nesting is so deep that the thread runs out of space, the thread dies with a StackOverflowError.[8] If your applications use lots of recursive algorithms or if your applications are built on top of a framework utilizing MVC design pattern such as Oracle ADF, you may want to leave StackThreadSize as defaults.
However, thread stacks are quite large, particularly for a 64-bit JVM. In [9], Scott Oaks has advised:
Finally, the total footprint of the JVM has a significant effect on its performance. So, footprint is one aspect of Java performance that should be commonly monitored.
- In most applications, 128k happens to be enough for the Java thread stack.
The stack size specified is too small, Specify at least 228kIn this article, we will discuss thread stack size tuning in JDK 8 (i.e., HotSpot VM).
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Default Thread Stack Size
When a new thread is launched, the Java virtual machine creates a new Java stack for the thread. As mentioned earlier, a Java stack stores a thread's state in discrete frames.[3] The Java virtual machine only performs two operations directly on Java Stacks: it pushes and pops frames.
The default thread stack size varies with JVM, OS and environment variables. To find out what your default ThreadStackSize is on your platform, use:[1]
java -XX:+PrintFlagsFinal -version
A typical value is 512k. It is generally larger for 64bit JVMs because references are 8 bytes rather than 4 bytes in size (but, you can compress oops or class pointers if you choose).[2] For example,[4]
In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in the 64-bit VM. On x86 Solaris/Linux it is 320k in the 32-bit VM and 1024k in the 64-bit VM.
On Windows, the default thread stack size is read from the binary (java.exe). As of Java SE 6, this value is 320k in the 32-bit VM and 1024k in the 64-bit VM.
In JDK 8, every time the JVM creates a thread, the OS allocates some native memory to hold that thread’s stack, committing more memory to the process until the thread exits. Thread stacks are fully allocated (i.e., committed, not just reserved) when they are created.
This means that if your application spawns a lot of threads, this can consume a significant amount of memory which could otherwise be used by your application or OS (or it can eventually leads to OutOfMemoryError).
You can reduce your stack size by running with the -Xss option. For example:
java -server -Xss256k
or Note that if you have installed a 64-bit VM binary for Linux, you can omit -server option.[5]java -server -XX:ThreadStackSize=256
Virtual Memory Map
In JDK 8, HotSpot installation comes with a feature named Native Memory Tracking (default: disabled). To enable it, use:
-XX:NativeMemoryTracking=[off|detail|summary]
After enabling NMT, you can examine the memory footprint taken by either Thread or Thread Stack using:
jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff |
detail.diff | shutdown] [scale= KB | MB | GB]
For example, on a 64-bit Linux platform, here is the thread stack size before and after setting
-Xss256k
:Before
Virtual memory map:[0x0000000040049000 - 0x000000004014a000] reserved and committed 1028KB for Thread Stack from
[0x00002aec741ca5e4] JavaThread::run()+0x24
[0x00002aec74083268] java_start(Thread*)+0x108
After
Virtual memory map:[0x0000000040078000 - 0x00000000400b9000] reserved and committed 260KB for Thread Stack from
[0x00002b02c69156e4] JavaThread::run()+0x24
[0x00002b02c67ce338] java_start(Thread*)+0x108
Conclusions
The thread stack is used to push stacks frames in nested method calls. If the nesting is so deep that the thread runs out of space, the thread dies with a StackOverflowError.[8] If your applications use lots of recursive algorithms or if your applications are built on top of a framework utilizing MVC design pattern such as Oracle ADF, you may want to leave StackThreadSize as defaults.
However, thread stacks are quite large, particularly for a 64-bit JVM. In [9], Scott Oaks has advised:
- As a general rule, many applications can actually run with a 128 KB stack size in a 32-bit JVM, and a 256 KB stack size in a 64-bit JVM.
- In a 64-bit JVM, there is usually no reason to set this value unless the machine is quite strained for physical memory and the smaller stack size will prevent applications from running out of native memory.
- On the other hand, using a smaller (e.g., 128 KB) stack size on a 32-bit JVM is often a good idea, as it frees up memory in the process size and allows the JVM to utilize a larger heap.
Finally, the total footprint of the JVM has a significant effect on its performance. So, footprint is one aspect of Java performance that should be commonly monitored.
References
- What Are the Default HotSpot JVM Values?
- JDK 8: UseCompressedClassPointers vs. UseCompressedOops
- The Java Stack
- Frequently Asked Questions About the Java HotSpot VM
- HotSpot VM Binaries: 32-Bit vs. 64-Bit
- How to Debug Native OutOfMemory in JRockit
- HotSpot: Monitoring and Tuning Metaspace in JDK 8
- Using -Xss to adjust Java default thread stack size to save memory and prevent StackOverflowError
- Java Performance: The Definitive Guide (Strongly recommended)
- Java thread stack size on 64-bit linux
- Learn More About Performance Improvements in JDK 8
- HotSpot Virtual Machine Garbage Collection Tuning Guide
- Getting Started with the G1 Garbage Collector
- Other JDK 8 articles on Xml and More
- Tuning that was great in old JRockit versions might not be so good anymore
- Trying to bring over each and every tuning option from a JR configuration to an HS one is probably a bad idea.
- Even when moving between major versions of the same JVM, we usually recommend going back to the default (just pick a collector and heap size) and then redoing any tuning work from scratch (if even necessary).
- HotSpot VM options (JDK 8)
434 comments:
«Oldest ‹Older 601 – 434 of 434Post a Comment