Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Causes of Tomcat memory overflow

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/03 Report--

Causes of Tomcat memory overflow

Memory overflow can easily occur when tomcat memory is not set up properly in a production environment. The cause of memory overflow is different, and of course it is handled in a different way.

Here according to the usual situation and related information to make a summary. There are three common situations:

1.OutOfMemoryError: Java heap space

2.OutOfMemoryError: PermGen space

3.OutOfMemoryError: unable to create new native thread.

Tomcat memory overflow solution

For the first two cases, it can be solved by setting the tomcat jvm parameter when there is no memory leak in the application itself. (Xms-Xmx-XX:PermSize-XX:MaxPermSize)

The last one may need to adjust the operating system and tomcat jvm parameters at the same time to achieve this.

The first is heap overflow.

Cause analysis:

The setting of JVM heap refers to the setting of memory space that JVM can allocate and use when java program is running.JVM automatically sets the value of Heap size when it starts, its initial space (i.e.-Xms) is 1x64 of physical memory, and the maximum space (- Xmx) is 1max of physical memory. It can be set with options such as-Xmn-Xms-Xmx provided by JVM. The size of Heap size is the sum of Young Generation and Tenured Generaion.

In JVM, this exception will be thrown if 98% of the time is spent on GC and less than 2% of the Heap size is available.

The maximum Heap Size should not exceed 80% of the available physical memory. Generally, the-Xms and-Xmx options should be set to the same, and the-Xmn should be set to the-XMX value of 1max 4.

If there is no memory leak, adjusting the-Xms-Xmx parameter can be solved.

-Xms: initial heap size

-Xmx: maximum heap size

But the size of the heap is affected in three ways:

1. The data model of the relevant operating system (32-bt or 64-bit) is limited; (on 32-bit systems, it is generally limited to 1.5Gbps; I tested the memory limit of the 1612M 64-bit operating system on a 2003 server system (physical memory: 4G and 6G jdk 1.6). )

two。 System's available virtual memory limit

3. The physical memory limit available to the system.

The heap size can be tested using the java-Xmx***M version command. The version number of jdk will appear if it is supported, and an error will be reported if it is not supported.

-Xms-Xmx is generally configured as the same, like set JAVA_OPTS=-Xms1024m-Xmx1024m

Its initial space (that is,-Xms) is 1x64 of physical memory, and the maximum space (- Xmx) is 1Comp4 of physical memory. You can use options such as-Xmn-Xms-Xmx provided by JVM to

Set up

As an example, the following provides the reference for setting parameters of java jvm in 1G memory environment:

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

JAVA_OPTS= "- server-Xms768m-Xmx768m-XX:PermSize=128m-XX:MaxPermSize=256m-XX:

NewSize=192m-XX:MaxNewSize=384m "

CATALINA_OPTS= "- server-Xms768m-Xmx768m-XX:PermSize=128m-XX:MaxPermSize=256m

-XX:NewSize=192m-XX:MaxNewSize=384m "

The server has 1GB of memory: JAVA_OPTS= "- server-Xms800m-Xmx800m-XX:PermSize=64M-XX:MaxNewSize=256m-XX:MaxPermSize=128m-Djava.awt.headless=true"

Server is 64-bit, 2 GB memory: JAVA_OPTS='-server-Xms1024m-Xmx1536m-XX:PermSize=128M-XX:MaxNewSize=256m-XX:MaxPermSize=256m'

-solution 1-Pluto-

Premise: the way startup.bat starts tomcat is executed

Linux server:

Catalina.sh in the / usr/local/apache-tomcat-5.5.23/bin directory

Add: JAVA_OPTS='-Xms512m-Xmx1024m'

Or JAVA_OPTS= "- server-Xms800m-Xmx800m-XX:MaxNewSize=256m"

Or CATALINA_OPTS= "- server-Xms256m-Xmx300m"

Windows server:

Join at the front of catalina.bat

Set JAVA_OPTS=-Xms128m-Xmx350m

Or set CATALINA_OPTS=-Xmx300M-Xms256M.

(the difference is that one sets jvm memory directly and the other sets tomcat memory. CATALINA_OPTS seems to be indistinguishable from JAVA_OPTS.)

Basic parameter description

-client,-server

These two parameters are used to set the running mode of the virtual machine, which must be used as the first parameter. Client mode starts faster, but runtime performance and memory management efficiency are not as efficient as server mode, and are usually used in client applications. In contrast, server mode starts more slowly than client, but achieves higher performance.

On windows, the default virtual machine type is client mode. If you want to use server mode, you need to add the-server parameter when starting the virtual machine to achieve higher performance. For server-side applications, server mode is recommended, especially for systems with multiple CPU. Server mode is used by default on Linux,Solaris.

In addition, under multi-cup, server mode is recommended

-Xms

Set the initial size of the available memory heap for the virtual machine, in bytes by default, which is an integral multiple of 1024 and greater than 1MB. You can set a large amount of memory in k (K) or m (M) units. The initial heap size is 2MB. Add "m" to indicate MB, otherwise it is KB.

For example:-Xms6400K,-Xms256M

-Xmx

Sets the maximum available size of the virtual machine, which defaults to bytes. The value must be an integer multiple of 1024 and greater than 2MB. You can set a large amount of memory in k (K) or m (M) units. The default maximum heap is 64MB.

For example:-Xmx81920K,-Xmx80M

When the virtual machine throws a java.lang.OutOfMemoryError: Java heap space error when the application requests a large memory run, you need to use-Xmx to set a large available memory heap.

PermSize/MaxPermSize: define the size of the Perm segment, that is, the size of the permanent storage area. PermSize is the amount of memory that initializes the Perm when JVM starts, and MaxPermSize is the maximum amount of Perm memory that can be occupied. These two values are generally set to the same in the user's production environment to reduce the overhead that the system spends on memory requests during operation.

If you start tomcat,OK with startup.bat, the setting takes effect. It is successful enough to allocate 200m memory.

-solution 2, Pluto, Musi,

Premise: the way startup.bat starts tomcat is executed

Set up Heap size manually

Windows server:

Modify TOMCAT_HOME/bin/catalina.bat by adding the following line above "echo" Using CATALINA_BASE: $CATALINA_BASE "":

Java code

Set JAVA_OPTS=%JAVA_OPTS%-server-Xms800m-Xmx800m-XX:MaxNewSize=256m

Note: JAVA_OPTS retains the previous settings.

Linux server:

Modify TOMCAT_HOME/bin/catalina.sh

Add the following line to "echo" Using CATALINA_BASE: $CATALINA_BASE "":

JAVA_OPTS= "$JAVA_OPTS-server-Xms800m-Xmx800m-XX:MaxNewSize=256m"

Note: $JAVA_OPTS retains the previous settings.

-solution 3-Pluto-

Premise: the way the system service executes windows to start tomcat

However, if you do not execute startup.bat to start tomcat but use windows's system services to start tomcat services, the above settings will not take effect.

That means set JAVA_OPTS=-Xms128m-Xmx350m didn't work. If 200m memory is allocated above, it will be OOM..

The windows service executes bin\ tomcat.exe. He reads the values in the registry, not the catalina.bat settings.

Solution:

Modify the registry HKEY_LOCAL_MACHINE\ SOFTWARE\ Apache Software Foundation\ Tomcat Service Manager\ Tomcat5\ Parameters\ JavaOptions

The original value is

-Dcatalina.home= "C:\ ApacheGroup\ Tomcat 5.0"

-Djava.endorsed.dirs= "C:\ ApacheGroup\ Tomcat 5.0\ common\ endorsed"

-Xrs

Add-Xms300m-Xmx350m

Restart the tomcat service, and the settings take effect

-solution 4 Pluto-

Premise: the way the system service executes windows to start tomcat

If "NT Service (NT/2000/XP only)" is checked when installing tomcat

After the installation is completed, there will be a tomcat.exe file in the "bin" directory of the installation directory.

Stop tomcat's service first.

In command line mode (enter CMD at run)

Change the directory to the bin directory of tomcat

Remove the service with the following command

Tomcat-uninstall "Apache Tomcat 4.1"

Next, write a batch.

The contents are as follows

Set SERVICENAME=Apache Tomcat 4.1

Set CATALINA_HOME=E:\ Tomcat 4.1.24

Set CLASSPATH=D:\ j2sdk1.4.1_01\ lib

Set JAVACLASSPATH=%CLASSPATH%

Set JAVACLASSPATH=%JAVACLASSPATH%; TALINA_HOME%\ bin\ bootstrap.jar

Set JAVACLASSPATH=%JAVACLASSPATH%; TALINA_HOME%\ common\ lib\ servlet.jar

Set JAVACLASSPATH=%JAVACLASSPATH%;%JAVA_HOME%\ lib\ tools.jar

Tomcat.exe-install "% SERVICENAME%"% JAVA_HOME%\ jre\ bin\ server\ jvm.dll"-Djava.class.path= "% JAVACLASSPATH%"-Dcatalina.home= "permanent TALINA_HOME%"-Xms512m-Xmx768m-start org.apache.catalina.startup.Bootstrap-params start-stop org.apache.catalina.startup.Bootstrap-params stop-out "permanent TALINA_HOME%\ logs\ stdout.log"-err "permanent TALINA_HOME%\ logs\ stderr.log"

Notice that the last line starts with tomcat.exe-install! Don't enter the car by hand to change the line and divide the line into several paragraphs. After saving, execute the bat file under the command line, and note that the "Services" window is closed when executed.

The second kind: permanent preservation area overflow

Cause analysis:

The full name of PermGen space is Permanent Generation space, which refers to the permanent storage area of memory. This memory is mainly stored in Class and Meta information by JVM. Class will be placed in PermGen space when it is Loader. Unlike the Heap area where class instances (Instance) are stored, GC (Garbage Collection) will not clean up PermGen space during the run time of the main program, so if you have a lot of CLASS in your application, PermGen space errors are likely to occur. This kind of error is common when the web server pre compile JSP. If you use a large number of third-party jar under your WEB APP, its size exceeds the default size of jvm (4m), then this error message will be generated. However, such problems are also easy to occur in current hibernate and spring projects. This may be because these frameworks dynamically class, and jvm's gc does not clean up PemGen space, which exceeds the default size of jvm (4m), resulting in a memory overflow.

Suggestion: move the same third-party jar files to the tomcat/shared/lib directory, which can reduce the repeated memory consumption of jar documents.

This one is generally larger-XX:PermSize-XX:MaxPermSize to solve the problem.

-initial size of the XX:PermSize permanent save area

-the initial maximum value of the XX:PermSize permanent save area

This is generally used in conjunction with the first item, such as set JAVA_OPTS=-Xms1024m-Xmx1024m-XX:PermSize=128M-XX:PermSize=256M.

One thing to note: the maximum heap memory tested by the java-Xmx***M version command is-Xmx and-XX:PermSize and for example, if the system supports a maximum jvm heap size of 1.5G, then-Xmx1024m-XX:PermSize=768M cannot be run.

-solution 1 VRO-

Linux server:

In the first line of catalina.sh, add:

JAVA_OPTS=

-Xms64m

-Xmx256m

-XX:PermSize=128M

-XX:MaxNewSize=256m

-XX:MaxPermSize=256m

Or

Add the following line to "echo" Using CATALINA_BASE: $CATALINA_BASE "":

JAVA_OPTS= "- server-XX:PermSize=64M-XX:MaxPermSize=128m

Windows server:

In the first line of catalina.bat, add:

Set JAVA_OPTS=-Xms64m-Xmx256m-XX:PermSize=128M-XX:MaxNewSize=256m-XX:MaxPermSize=256m

-solution 2, Pluto, Musi,

Modify TOMCAT_HOME/bin/catalina.bat (catalina.sh under Linux), in the Java code

Add the following line to "echo" Using CATALINA_BASE: $CATALINA_BASE "":

Set JAVA_OPTS=%JAVA_OPTS%-server-XX:PermSize=128M-XX:MaxPermSize=512m

Add the following line to "echo" Using CATALINA_BASE: $CATALINA_BASE "":

Set JAVA_OPTS=%JAVA_OPTS%-server-XX:PermSize=128M-XX:MaxPermSize=512m

The catalina.sh is as follows:

Java code

JAVA_OPTS= "$JAVA_OPTS-server-XX:PermSize=128M-XX:MaxPermSize=512m"

JAVA_OPTS= "$JAVA_OPTS-server-XX:PermSize=128M-XX:MaxPermSize=512m"

Third: unable to create a new thread.

This phenomenon is rare and strange, mainly related to the ratio of jvm to system memory.

This is strange because JVM has been allocated a large amount of memory (such as 1.5G) by the system, and it takes up at least half of the available memory. It has been found that the more memory you allocate to JVM in the case of a large number of threads, the more likely the above error is to occur.

Cause analysis

(learn the reason from this blog: http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html):

Each 32-bit process can use up to 2G of available memory because the other 2G is reserved by the operating system. Assuming that 1.5g is used for JVM, 500m of memory is still available. Some of this 500m memory must be used to load the system dll, so the real remaining may only be 400m. Now the key point appears: when you use Java to create a thread, a Thread object will also be created in JVM memory, but a real physical thread will also be created in the operating system (see JVM specification), and the operating system will create this physical thread in the remaining 400m memory. Instead of creating it in JVM's 1500m memory heap. In jdk1.4, the default stack size is 256KB, but in jdk1.5, the default stack size is 1m per thread, so we can only create up to 400m of available threads in the remaining 400m of available memory.

The conclusion is that to create more threads, you must reduce the maximum memory allocated to JVM. Another way is to host JVM in your JNI code.

Give a formula for estimating the maximum number of threads that can be created:

(MaxProcessMemory-JVMMemory-ReservedOsMemory) / (ThreadStackSize) = Number of threads

For jdk1.5, assume that the operating system retains 120m of memory:

1.5GB JVM: (2GB-1.5Gb-120MB) / (1MB) = ~ 380 threads

1.0GB JVM: (2GB-1.0Gb-120MB) / (1MB) = ~ 880threads

There is a startup option in 2000/XP/2003 's boot.ini, such as / PAE / 3G, which can expand the maximum memory of the user process to 3G, when the operating system can only occupy up to 1 gigabyte of virtual memory. That should allow JVM to create more threads.

Therefore, this situation needs to be adjusted in combination with the operating system.

Therefore: we need to make different diagnoses of tomcat memory allocation according to different situations in order to solve the problem fundamentally.

Detect current JVM memory usage:

System.out.println ("JVM MAX MEMORY:" + Runtime.getRuntime (). MaxMemory () / 1024 take 1024 + "M")

System.out.println ("JVM IS USING MEMORY:" + Runtime.getRuntime (). TotalMemory () / 1024 take 1024 + "M")

System.out.println ("JVM IS FREE MEMORY:" + Runtime.getRuntime (). FreeMemory () / 1024 take 1024 + "M")

All three methods refer to the memory usage of JVM rather than the memory of the operating system.

The maxMemory () method returns the maximum memory that the java virtual machine (this process) can dig from the operating system, in bytes. If the-Xmx parameter is not added when running the java program, it is 64 megabytes, which means that maxMemory () returns about 64 million 1024 bytes, which is the maximum memory that the java virtual machine can dig from the operating system by default. If the-Xmx parameter is added, the value following this parameter will prevail, for example, java-cp ClassPath-Xmx512m ClassName, then the maximum memory is 512110240124 bytes.

The totalMemory () method returns the amount of memory that the java virtual machine has now dug from the operating system, which is all the memory occupied by the java virtual machine at that time. If you do not add the-Xms parameter when running java, then, in the process of running the java program, memory is always slowly dug from the operating system, basically as much as you use to dig up to maxMemory (), so totalMemory () is slowly increasing. If the-Xms parameter is used, the program will unconditionally dig the amount of memory defined after-Xms at startup, and then dig again when the memory is about the same.

What is freeMemory ()? I just mentioned that if the-Xms parameter is not added when running java, then, in the process of running java programs, memory is always slowly dug from the operating system, basically as much as it takes, but when the java virtual machine is 100%, it will dig a little more. The memory dug up but not used is actually freeMemory (). So the value of freeMemory () is usually very small, but if you use-Xms when running a java program, at this time, because the program will unconditionally dig the amount of memory defined after-Xms from the operating system, at this time, most of the dug memory may not be used, so freeMemory () may have some

-solution--

JVM heap size adjustment

Sun HotSpot 1.4.1 uses a generational collector, which divides the heap into three main domains: new, old, and permanent. All new objects generated by Jvm are placed in the new domain. Once the object goes through a certain number of garbage collection cycles, it gets its useful life and enters the old domain. Jvm stores class and method objects in the permanent domain. In terms of configuration, the permanent domain is a separate domain and is not considered part of the heap.

How to control the size of these fields is described below. You can use-Xms and-Xmx to control the original size or maximum value of the entire heap.

The following command sets the initial size to 128m:

Java-Xms128m

-Xmx256m to control the size of the new domain, you can use-XX:NewRatio to set the proportion of the new domain in the heap.

The following command sets the entire heap to 128m and the new domain ratio to 3, that is, the ratio of the new domain to the old domain is 1:3, and the new domain is 1x4 or 32m of the heap:

Java-Xms128m-Xmx128m

-XX:NewRatio = 3 can use-XX:NewSize and-XX:MaxNewsize to set the initial and maximum values for the new domain.

The following command sets the initial and maximum values of the new field to 64m:

Java-Xms256m-Xmx256m-Xmn64m

The default size of the permanent domain is 4m. When you run the program, jvm resizes the permanent domain to meet your needs. With each adjustment, jvm does a full garbage collection on the heap.

Use the-XX:MaxPerSize flag to increase the permanent domain size. When WebLogic Server applications load more classes, it is often necessary to increase the maximum value of the permanent domain. When jvm loads classes, the number of objects in the permanent domain increases dramatically, causing jvm to constantly resize the permanent domain. To avoid tuning, you can use the-XX:PerSize flag to set the initial value.

The initial value of the permanent field is set to 32m, and the maximum value is set to 64m.

Java-Xms512m-Xmx512m-Xmn128m-XX:PermSize=32m-XX:MaxPermSize=64m

By default, HotSpot uses the replication collector in the new domain. The domain is generally divided into three parts. The first part is Eden, which is used to generate new objects. The other two parts are called salvage space. When Eden is full, the collector stops the application and copies all reachable objects to the current from salvage space. Once the current from salvage space is full, the collector copies reachable objects to the current to salvage space. From and to Rescue Space swap roles. Objects that remain active will continue to replicate in the rescue space until they are used and transferred to the old domain. Use-XX:SurvivorRatio to control the size of the subspace of the new domain.

Like NewRation, SurvivorRation specifies the ratio of a rescue domain to an Eden space. For example, the following command sets the new domain to 64m, with 32m for Eden and 16m for each rescue domain:

Java-Xms256m-Xmx256m-Xmn64m-XX:SurvivorRation = 2

As mentioned earlier, by default, HotSpot uses a replication collector for the new domain and a mark-clear-compression collector for the old domain. Using replication collectors in a new domain makes a lot of sense because most of the objects generated by the application are short-lived. Ideally, all transition objects will be collected when they are moved out of Eden space. If this is possible, and the objects removed from the Eden space are long-lived, then in theory they can be moved into the old domain immediately to avoid repeated replication in the rescue space. However, applications are not suitable for this ideal state because they have a small number of medium-and long-lived objects. It is best to keep these medium-and long-lived objects in the new domain, because it is always cheaper to copy a small number of objects than to compress the old domain. To control the replication of objects in the new domain, use-XX:TargetSurvivorRatio to control the proportion of salvage space (this value is to set the proportion of salvage space used. If the rescue space is 1m, a value of 50 indicates that 500K is available. The value is a percentage and the default value is 50. When larger stacks use lower sruvivorratio, you should increase this value to 80 to 90 to make better use of salvage space. The upper limit can be controlled with-XX:maxtenuring threshold.

To place that all replication occurs and you want the object to extend from eden to the old domain, you can set MaxTenuring Threshold to 0. After the setting is complete, the rescue space is actually no longer used, so you should set SurvivorRatio to the maximum value to maximize Eden space, as follows:

Java... -XX:MaxTenuringThreshold=0-XX:SurvivorRatio=50000...

Garbage collection description:

Garbage collection is divided into multiple levels. Garbage collection at level 0 (Full) will collect garbage in OLD segment; level 1 or above is partial garbage collection and only garbage in Young will be collected. Memory overflow usually occurs after garbage collection in OLD segment or Perm segment, and there is still no memory space to accommodate new Java objects.

When a URL is accessed, the memory request process is as follows:

A. JVM attempts to initialize a memory area in Eden for related Java objects

b. When there is enough Eden space, the memory request ends. Otherwise, to the next step,

C. JVM attempts to release all inactive objects in Eden (this belongs to garbage collection of 1 or higher); after release, if there is still not enough Eden space for new objects, try to put some of the active objects in Eden into the Survivor area / OLD area

D. the Survivor area is used as the intermediate exchange area between Eden and OLD. When there is enough space in the OLD area, the objects in the Survivor area will be moved to the Old area, otherwise they will be retained in the Survivor area.

e. When there is not enough space in the OLD area, JVM will conduct a full garbage collection (level 0) in the OLD area.

f. After complete garbage collection, if the Survivor and OLD areas are still unable to store some objects copied from Eden, resulting in JVM being unable to create memory areas for new objects in the Eden area, a "out of memory error" will occur.

Java heap related parameters:

Ms/mx: defines the total size of the YOUNG+OLD segment. Ms is the memory size of the YOUNG+OLD when JVM starts, and mx is the maximum YOUNG+OLD memory size that can be occupied. These two values are generally set to the same in the user's production environment to reduce the overhead that the system spends on memory requests during operation.

NewSize/MaxNewSize: defines the size of the YOUNG segment. NewSize is the memory size of YOUNG when JVM starts, and MaxNewSize is the maximum YOUNG memory size that can be occupied. These two values are generally set to the same in the user's production environment to reduce the overhead that the system spends on memory requests during operation.

PermSize/MaxPermSize: defines the size of the Perm segment. PermSize is the memory size of Perm when JVM starts, and MaxPermSize is the maximum Perm memory size that can be occupied. These two values are generally set to the same in the user's production environment to reduce the overhead that the system spends on memory requests during operation.

SurvivorRatio: sets the ratio of Survivor space to Eden space

Example:

MEM_ARGS= "- Xms512m-Xmx512m-XX:NewSize=256m-XX:MaxNewSize=256m-XX:PermSize=128m-XX:MaxPermSize=128m-XX:SurvivorRatio=6"

In the above example:

YOUNG+OLD: 512M

YOUNG: 256M

Perm: 128M

Eden: YOUNG*6/ (6 / 1 / 1) = 192 M

Survivor: YOUNG/ (6 / 1 / 1) = 32m

Total size of Java heap = YOUNG+OLD+Perm=640M

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report