JVM memory overflow and reasonable configuration in Tomcat

Reprint address: http://blog.csdn.net/ye1992/article/details/9344807

 

Tomcat itself cannot run directly on the computer, and needs to rely on an operating system based on hardware and a Java virtual machine. The essence of Tomcat's memory overflow is JVM memory overflow, so at the beginning of this article, you should first introduce the knowledge of Java JVM in detail.

1. Introduction to Java JVM Memory

The JVM manages two types of memory, heap and non-heap. According to the official statement: "The Java virtual machine has a heap, which is the runtime data area from which memory for all class instances and arrays is allocated. The heap is created when the Java virtual machine starts." "The heap in the JVM The external memory is called non-heap memory (Non-heap memory). In short, the heap is the memory accessible to Java code, which is reserved for developers; non-heap is reserved for the JVM, so the memory required for method area, JVM internal processing or optimization (such as JIT compiled code) Cache), each class structure (such as runtime constant pool, field and method data), and the code of methods and constructors are in non-heap memory, which is different from the heap, and its space is not released by the GC during runtime.

(1). Heap memory allocation
The initial allocated memory of the JVM is specified by -Xms, and the default is 1/64 of the physical memory; the maximum allocated memory of the JVM is specified by -Xmx, and the default is 1/4 of the physical memory. When the default free heap memory is less than 40%, the JVM will increase the heap until the maximum limit of -Xmx; when the free heap memory is greater than 70%, the JVM will reduce the heap until the minimum limit of -Xms. Therefore, the server generally sets -Xms, -Xmx equal to avoid adjusting the size of the heap after each GC. You can use the options such as -Xmn -Xms -Xmx provided by the JVM to set the heap memory. Generally, the -Xms and -Xmx options should be set to the same, and -Xmn is 1/4 of the -Xmx value. The maximum value of the heap is recommended Set to 80% of the maximum available memory.

The size of the initialization heap is the size of the memory that the JVM requests from the system at startup. In general, this parameter is not important. However, some applications will rapidly occupy more memory under heavy load. At this time, this parameter is very important. If the memory used when the JVM is started is relatively small and many objects are initialized in this case , the JVM must repeatedly increase the memory to meet the usage. For this reason, we generally set -Xms and -Xmx to be the same size, and the maximum heap size is limited by the physical memory used by the system. Generally, applications that use large amounts of data use persistent objects, and memory usage is likely to grow rapidly. When the memory required by the application exceeds the maximum heap size, the JVM will prompt a memory overflow and cause the application service to crash. Therefore, if Xms exceeds the Xmx value, or the sum of the heap maximum and non-heap maximum exceeds the physical memory or the maximum limit of the operating system, the server will not start up.

(2). Non-heap memory allocation
It is also called a permanently saved area, which is used to store Class and Meta information. Class is put into this area when it is loaded. It is different from the Heap area where the class instance (Instance) is stored, and the GC (Garbage Collection) will not clean up the PermGen space during the runtime of the main program. The JVM uses -XX:PermSize to set the initial value of non-heap memory, the default is 1/64 of the physical memory; the maximum non-heap memory size is set by XX:MaxPermSize, the default is 1/4 of the physical memory. The GC will not clean up the PermGen space, so if your app loads a lot of CLASS, it is likely to have a PermGen space error.

(3). JVM memory limit (maximum value)
First of all, the JVM memory is limited to the actual maximum physical memory (nonsense!, huh). If the physical memory is infinite, the maximum JVM memory has a great relationship with the operating system. To put it simply, although the controllable memory space of a 32-bit processor has 4GB, the specific operating system will impose a limit, which is generally 2GB-3GB (generally 1.5G-2G under Windows system and 1.5G-2G under Linux system). 2G-3G), and processors above 64bit will not have restrictions.

Two, three kinds of memory overflow exception introduction

1. OutOfMemoryError: Java heap space heap overflow

The main problem with memory overflow is in this situation. This exception message is thrown when 98% of the time in the JVM is used for GC and the available Heap size is less than 2%.

 2. OutOfMemoryError: PermGen space non-heap overflow (permanent save area overflow)

This kind of error is common when the web server precompiles the JSP. If your WEB APP uses a large number of third-party jars, the size of which exceeds the default size of jvm (4M), then this error message will be generated. If the web app uses a large number of third-party jars or the application has too many class files and the MaxPermSize is set to a small value, it will also cause excessive memory usage and overflow, or the tomcat will not clear the front during hot deployment. The loaded environment will only change the context to the newly deployed one, and there will be more and more non-heaped content.

3. OutOfMemoryError: unable to create new native thread. Unable to create a new thread

This phenomenon is relatively rare and strange, mainly related to the ratio of jvm to system memory. This weirdness is because the JVM has been allocated a lot of memory by the system (say 1.5G) and it takes at least half of the available memory.

 

3. Java JVM memory configuration

1. There are four parameters for JVM memory allocation settings

-Xmx Java Heap maximum value, the default value is 1/4 of physical memory;

The initial value of -Xms Java Heap, the server-side JVM is best to set -Xms and -Xmx to the same value, the development and testing machine JVM can keep the default value;

-Xmn Java Heap Young area size, if you are not familiar with it, it is best to keep the default value;

-Xss The stack size of each thread, if you are not familiar with it, it is best to keep the default value;

-XX:PermSize: Set the permanent storage area of ​​the memory;

-XX:MaxPermSize: Set the permanent storage area of ​​the maximum memory;

-XX:PermSize: Set the permanent storage area of ​​the memory;

-XX:NewSize: Set the default size of the 'new generation' of the JVM heap;

-XX:MaxNewSize: Set the maximum size of the 'new generation' of the JVM heap;

2. How to set the memory allocation of the JVM

(1) When starting and using the JVM at the command prompt (only valid for the currently running class Test):

java -Xmx128m -Xms64m -Xmn32m -Xss16m Test

(2) When the JVM is started and used in an integrated development environment (such as eclipse):

a. Open eclipse.ini in the eclipse root directory, the default content is (the JVM memory allocation for running the current development tool is set here): -vmargs -Xms40m -Xmx256m -vmargs indicates that the following parameters are set for the virtual machine, which can be modified You can also add -Xmn, -Xss to the parameter value. In addition, you can also set non-heap memory in eclipse.ini, such as: -XX:PermSize=56m, -XX:MaxPermSize=128m.

b. Open eclipse-window-preference-java-installed JRE (valid for all java programs running in the current development environment) Edit the currently used JRE, and enter in the default VM parameters: -Xmx128m -Xms64m -Xmn32m –Xss16m.

c. Open eclipse - run - run - Java application (only valid for the set java class) Select the class to set memory allocation - argument, and enter: -Xmx128m -Xms64m -Xmn32m -Xss16m in the VM argument. Note : If both b and c are set in the same development environment, the b setting is valid, and the c setting is invalid, for example: The setting of the development environment is: -Xmx256m, and the setting of the class Test is: -Xmx128m -Xms64m, then run Test The effective settings are: -Xmx256m -Xms64m.

(3) When starting and using the JVM in a server environment (such as Tomcat) (valid for Java programs in the current server environment):

a. Set environment variables: Variable name: CATALINA_OPTS Variable value: -Xmx128m -Xms64m -Xmn32m -Xss16m.

b. Open the bin folder in the root directory of Tomcat, edit catalina.bat, and replace %CATALINA_OPTS% (four places in total) with: -Xmx128m -Xms64m -Xmn32m -Xss16m.

c. If there is no catalina.bat, only tomcat.exe and tomcat6w.exe; you can right-click to configure --Java--java option after starting tomcat6w.exe and enter:

-Xmx256m –Xms64m

You can also find the registry HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions The original value is -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup \Tomcat 6.0\common\endorsed" -Xrs Add -Xms300m -Xmx350m (Mine is adding -Xmx350m, tomcat can start, adding -Xms300m -Xmx350m but tomcat can't start) Restart the tomcat service, the settings will take effect.

3. View JVM memory information

Runtime.getRuntime().maxMemory(); //Maximum available memory, corresponding to -Xmx 

Runtime.getRuntime().freeMemory(); //Current JVM free memory 

Runtime.getRuntime().totalMemory(); //The total amount of memory occupied by the current JVM, whose value is equivalent to the sum of the memory used by the current JVM and freeMemory() 

About maxMemory(), freeMemory() and totalMemory(): maxMemory() is the maximum available memory of the JVM, which can be set by -Xmx, the default value is 1/4 of the physical memory, and the setting cannot be higher than the computer physical memory; totalMemory() It is the total amount of memory occupied by the current JVM, and its value is equivalent to the sum of the memory used by the current JVM and freeMemory(), which will increase as the memory used by the JVM increases; freeMemory() is the free memory of the current JVM, because the JVM only needs to The physical memory is only used when the memory is used, so the value of freeMemory() is generally small, and the actual available memory of the JVM is not equal to freeMemory(), but should be equal to maxMemory()-totalMemory()+freeMemory().

4. Example, the parameter setting reference of java jvm in 1G memory environment is given below

JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "

Large-scale web projects cannot be started with the memory space allocated by tomcat by default. If tomcat is not started in myeclipse, you can set tomcat like this:

Add this sentence to TOMCAT_HOME\bin\catalina.bat:

set JAVA_OPTS= -Xmx1024M -Xms512M -XX:MaxPermSize=256m

If you want to start in myeclipse, the above modification will not work, you can set it as follows:

Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK panel

Add Optional Java VM arguments: -Xmx1024M -Xms512M -XX:MaxPermSize=256m

For a single .class, you can use the following method to set the jvm memory when Test is running. java -Xms64m -Xmx256m Test -Xms is to set the size of memory initialization -Xmx is to set the maximum size of memory that can be used.

Fourth, JVM memory configuration and GC

What needs to be considered is the garbage collection mechanism provided by Java. The JVM's heap size determines how much time and how often the JVM spends collecting garbage. The acceptable rate of garbage collection is application-dependent and should be adjusted by analyzing the timing and frequency of actual garbage collections. If the heap size is large, full garbage collection will be slow, but less frequently. If you align the heap size with the memory needs, full collections are fast, but more frequent. The purpose of heap sizing is to minimize garbage collection time in order to maximize the processing of client requests within a certain amount of time. When benchmarking, in order to ensure the best performance, the size of the heap should be set large to ensure that garbage collection does not occur during the entire benchmarking process. If the system spends a lot of time collecting garbage, reduce the heap size. A full garbage collection should take no more than 3-5 seconds. If garbage collection becomes the bottleneck, then you need to specify the size of the heap, examine the detailed output of garbage collection, and study the effect of garbage collection parameters on performance. In general, you should use 80% of physical memory as the heap size. When adding processors, remember to increase memory because allocation can be done in parallel, while garbage collection is not.

Java Heap is divided into 3 areas:

1.Young 2.Old 3.Permanent. Young holds the object that was just instantiated. When the area is filled, the GC will move the object to the Old area. The Permanent area is responsible for saving reflection objects, which is not discussed in this article.

The JVM has two GC threads:
the first thread is responsible for recycling the Young area of ​​the Heap;
the second thread traverses the Heap when the Heap is insufficient, and upgrades the Young area to the Older area. The size of the Older area is equal to -Xmx minus -Xmn, The value of -Xms cannot be set too high, because the second thread is forced to run and will reduce the performance of the JVM.

Why do some programs have frequent GC? There are the following reasons:
1. System.gc() or Runtime.gc() is called in the program.
2. Some middleware software calls its own GC methods, and you need to set parameters to disable these GCs.
3. Java's Heap is too small, generally the default Heap value is very small.
4. Frequent instantiation of objects, Release objects try to save and reuse objects at this time, such as using StringBuffer() and String().

If you find that after each GC, the remaining space of the Heap will be 50% of the total space, which means that your Heap is in a healthy state. Many server-side Java programs should preferably have 65% of the remaining space after each GC.

Experience:
1. It is best for the server-side JVM to set -Xms and -Xmx to the same value. In order to optimize GC, it is best to make the value of -Xmn approximately equal to 1/3 of -Xmx.
2. A GUI program should preferably run the GC every 10 to 20 seconds, each time completing within half a second.

Note:
1. Although increasing the size of Heap reduces the frequency of GC, it also increases the time of each GC. And while the GC is running, all user threads will be suspended, that is, the Java application will not do any work during the GC.
2. The heap size does not determine the memory usage of the process. The memory usage of a process is larger than the value defined by -Xmx because Java allocates memory for other tasks, such as stacks per thread, etc.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326447273&siteId=291194637