Abstract:Insufficient Java heap capacity can have a great impact on the performance. This will undoubtedly cause unnecessary troubles to the program, this article summarizes the five major reasons that affect the insufficient Java heap capacity and how to optimize it skillfully?
This article is written by Pierre, a senior System Architect with more than 10 years of experience. He specializes in Java EE, middleware, and JVM technologies. Based on his years of practical experience, he found that many performance problems are caused by insufficient Java heap capacity and optimization. Next, he will share with you five useful Java heap optimization techniques.
1. JVM: fear of something hard to understand
Never think that, through configuration, optimization, you can eliminate problems you do not understand. Some people think that Java programmers do not need to know the internal JVM memory management. Without a doubt, this idea is obviously incorrect. to broaden your knowledge and improve troubleshooting capabilities, you must understand and learn about JVM memory management.
For beginners of Java or Java EE, Java Heap optimization and troubleshooting are very challenging. The following are some typical cases:
The client environment faces regular OutOfMemoryError and has a great impact on the business.
What should your development team do to solve this problem under such great pressure?
Where is the error?
First, do you find out the root cause of the problem? Do not have a correct understanding of the development environment (specifications, load conditions, and so on. Web search is an excellent learning method and knowledge sharing tool. However, you must analyze and solve the problem based on your actual project.
There may be a lack of basic JVM and JVM memory management skills to prevent you from connecting all the points.
The first trick today is to help you understand the basic JVM principles and their distinctive memory space. This knowledge is very important. It can help you make effective optimization policies, predict future impacts more correctly and reasonably, and know in advance what optimization work needs to be done in the future. Next let's take a look at the JVM Reference Guide:
JVM memory is divided into three Memory Spaces
- Java Heap: Applicable to All JVM vendors. It is usually used to split YoungGen (seedlings) and OldGen (lifetime) spaces.
- PermGen (permanent generation): Applicable to Sun HotSpot VM (the PermGen space will be deleted in Java7 or Java8 updates)
- Native Heap (C-Heap): Applicable to All JVM vendors.
We recommend that you read the following articles. We recommend that you download Sun's Java memory management White Paper and OpenJDKS and read them carefully.
- Sun HotSpot VM
- IBM VM
- Oracle JRockit VM
- Sun (Oracle)-Java memory management white paper
- OpenJDK-Open-source Java implementation
As you can see, JVM memory management is more complex than setting the maximum value using Xmx. You need to view each angle, including local and PermGen requirements, and view physical memory availability (CPU core) from the host ).
In large Java Heap and small local Heap competitions, 32-bit virtual machines may become quite tricky. Try to set up a large heap on a 32-bit VM such as 2.5 GB +. The OutOfMemoryError exception is thrown based on factors such as application occupation and thread quantity. 64-bit JVM can solve this problem, but the cost of physical resource availability and garbage collection is still limited (the cost is mainly concentrated on GC size collection ). The maximum value does not indicate that it is the best, so do not assume that 20 Java EE applications can be run on a 16 GB 64-bit virtual machine.
2. Data and Applications are King: Review static occupancy requirements
Applications and related data determine the Java heap space occupation requirements. With static memory, you can "predict" the memory requirements below:
- Determine how many different applications will be deployed to a separate pre-planned JVM process, such as how many ear files, war files, and jar files. The more applications deployed on a JVM, the more requirements on the local heap.
- Determine how many classes need to be loaded at runtime: including third-party APIs. The more class loaders and classes are loaded at runtime, the higher the demand for hot spot VM PermGen space and internal JIT-Related Optimization objects.
- Determine the data cache usage, such as loading the internal cache data structure (and third-party APIs) of the application, such as the data cache in the database and reading data from the file. The more data cache is used, the higher the Java Heap OldGen space requirement.
- Determine the number of middleware threads allowed. This is very important because the Java thread requires enough local memory; otherwise, an OutOfMemoryError exception will be thrown.
The more applications deployed on the JVM process, the higher the requirements for local memory and PermGen space. The data cache is not serialized as a disk or database. It requires additional memory from the OldGen space.
Try to make a reasonable assessment of static memory usage. It is very useful to set the starting point of some JVM capabilities before the real data test. For 32-bit JVMs, we do not recommend a Java heap with a size greater than 2 GB (-Xms2048m,-Xmx2048m ), for Java EE applications and threads, this requires sufficient memory and local heap PermGen.
This evaluation is very important because too many applications are deployed on a 32-bit JVM process, which can easily lead to local heap depletion, especially in multi-threaded environments.
For 64-bit JVM, A 3 GB or 4 GB Java Heap/JVM process is the recommended starting point.
3. Business traffic setting rules: Review dynamic memory usage requirements
Business traffic usually determines the dynamic memory usage. By observing various monitoring tools, we can find that the jvm gc heartbeat generated by concurrent users and requests is caused by frequent creation and garbage collection of short-term or long-term objects.
In a typical 32-bit JVM, the Java heap size is set to 2 GB (using the generational and concurrent collectors). Generally, 500 MB YoungGen is allocated space and 1.5 GB of OldGen space.
Minimizing the frequency of major GC collection is a key factor in achieving optimal performance, so it is important to understand and evaluate the amount of memory needed during peak hours.
Again, the application type and data determine the memory requirements. The application type (long lived object) of the shopping cart involves large and non-serialized session data, which usually requires a large Java heap and a lot of OldGen space. Stateless and XML Processing (many short-lived objects) heavy applications require appropriate YoungGen space to minimize the frequency of major collections.
For example:
You have five ear applications (more than 2000 Java classes) to be deployed (including middleware code)
As you can see, in this case, 32-bit JVM processes cannot meet the requirements. A typical solution is to split traffic on several JVM processes or physical hosts (assuming there are enough hardware and CPU cores available.
Most of the time, business traffic will drive memory usage. Unless you need a large amount of data cache to achieve proper performance, the typical portal application website (media) has heavy application requirements. When there are too many data caches, you should mark them with a yellow sign. It is best to review some design elements earlier.
4. tailored
You should:
Multiple JVM (middleware) processes are required.
Wait, this is not enough. Although the above information is crucial, and "best guess" is made about the Java heap settings ", simulate the application behavior and perform appropriate analysis, load, and performance tests to verify the Java heap memory requirements.
We recommend the Jprofiler tool to you. The best way to learn how to use a analyzer is to correctly understand the memory usage of the application. Another method is to use the Eclipse MAT tool to perform heap dump analysis based on the existing environment. Heap dump is very powerful. It allows you to view and understand the overall memory usage of the Java heap, including the data related to the class loader and the memory usage analysis, especially the memory leakage.
Java analyzer and heap dump analysis tools allow you to understand and verify the application's memory footprint, including memory leakage detection and solutions. Load Testing and performance testing are essential. By simulating concurrent users to verify that early evaluations are correct, it will expose application bottlenecks and allow you to fine-tune them. We recommend a very easy-to-use tool: Apache Jmeter.
Finally, let's take a look at this situation. The application is very normal in the Java EE environment until one day the device fails to start completely normal, such as hardware problems. What happened to sudden decrease in the environment running capacity and overall environment?
There are many reasons for the domino effect, but the lack of JVM tuning and Failover capabilities (short-term extra load) is common. If the JVM process runs in more than 80% OldGen space and frequent garbage collection, how do you anticipate failover scenarios?
The previously simulated load and performance tests should simulate such a scenario, and adjust your tuning settings so that your Java Heap has enough buffer to handle additional loads (additional objects) in the short term. This is mainly applicable to dynamic memory usage, because failover means to redirect some fixed concurrent users to available JVM processes (middleware instances ).
5. Divide and conquer
The premise is that you have completed dozens of load tests. The JVM has no leakage and your application memory cannot be reduced. You have tried several optimization policies, for example, using a 64-bit Java heap space of more than 10 Gb. Multiple GC policies, even so, have not found a suitable acceptable performance level?
Appropriate vertical and horizontal scaling, compared to the current JVM specification, includes setting up JVM processes on each physical host and across multiple hosts to meet the overall throughput and capacity. If you break the list of applications in several logical warehouses, their own JVM processes, threads, and tuning values, the fault tolerance capability of the IT environment will be more powerful.
The "divide and conquer" policy includes splitting application traffic to multiple JVM processes. The following are some splitting techniques:
When you find that you have spent a lot of time tuning 64-bit JVM processes, you should take a good look at your middleware and JVM deployment policies and use vertical and horizontal scaling. The implementation of this policy requires more hardware support, but in the long run, it is very effective and beneficial. (Zhang hongyue/compilation)