tomcat内存溢出全记录

23 篇文章 0 订阅
22 篇文章 0 订阅

目录

 

内存溢出解决记录

内存及GC 的相关参数


内存溢出解决记录

项目平稳运行到1个月5天时候,tomcat服务突然崩溃,首先查看下tomcat的日志,如下:

24-Sep-2019 10:39:06.628 严重 [http-nio-9090-exec-53]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Request processing failed;        
nested exception is java.lang.NullPointerException] with root cause        
java.lang.NullPointerException        
24-Sep-2019 10:40:55.663 严重 [http-nio-9090-exec-19]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]         
in context with path [/web_project_resources] threw exception [Request processing failed;        
nested exception is java.lang.NullPointerException] with root cause        
java.lang.NullPointerException        
24-Sep-2019 10:44:46.997 严重 [http-nio-9090-exec-19]         
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Handler processing failed;        
nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause        
java.lang.OutOfMemoryError: Java heap space        
24-Sep-2019 10:45:29.173 严重 [http-nio-9090-exec-58]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Handler processing failed;        
nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause        
java.lang.OutOfMemoryError: Java heap space        
24-Sep-2019 10:45:29.173 严重 [http-nio-9090-exec-57]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Handler processing failed;        
nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause        
java.lang.OutOfMemoryError: Java heap space        
24-Sep-2019 10:45:29.173 严重 [http-nio-9090-exec-56]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Handler processing failed;        
nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause        
java.lang.OutOfMemoryError: Java heap space        
24-Sep-2019 10:45:29.174 严重 [http-nio-9090-exec-18]        
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]        
in context with path [/web_project_resources] threw exception [Request processing failed;         
nested exception is java.lang.NullPointerException] with root cause        
java.lang.NullPointerException

根据日志内容进行解析:

[http-nio-9090-exec-xx],这里的http-nio指得是tomcat连接器Connector的三种模式之一(bio/nio/apr)由于本次使用的是tomcat8.5版本,所以tomcat8.5连接器默认是NIO模式(tomcat7以及之前使用BIO)如果使用tomcat7及以前版本想配置成nio模式需要在conf/server.xml中<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />改成<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" />

另外Http请求默认使用了HTTP/1.1协议处理,当然tomcat8.5以上版本都支持了最新的HTTP/2.0协议。

说句题外话,tomcat对http/2.0的支持实际是从tomcat9开始的,Apache Tomcat 9.0.0.M1 是 9.0.x 的第一个里程碑版本,提供 9.0.x 的新特性早期预览,有如下值得关注的改进:

①新增 HTTP/2 支持和 TLS 虚拟主机
②实现当前 Servlet 4.0 规范草案
③BIO connectors 不再支持 Windows Itanium 和 Comet
comet取消,因为http2.0 加入了 server push的功能。

不过,现在已经把http2.0的支持移植到了tomcat8.5版本中。

“exec”表达执行,exec-xx后面接的数字只的是tomcat此时执行的线程,所以[http-nio-9090-exec-xx]是tomcat
处理当前请求的线程名字。tomcat内部有一个处理任务请求的线程池,有请求的时候会被放在线程池中执行,请求处理结束返回给浏览器后,线程池回收线程。

org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [tug_ciimp]
in context with path [/web_project_resources] threw exception [Request processing failed;
nested exception is java.lang.NullPointerException] with root cause

这段话的意思其实就是说tomcat在执行名为tug_ciimp这个servlet容器时,这个容器上下文/web_project_resources
这个路径的时候抛出异常,该异常因为root用户引起,请求程序失败,发生嵌套的异常为:空指针异常(NullPointerException)

同理,解析出:[Handler processing failed;nested exception is java.lang.OutOfMemoryError:
Java heap space] with root cause java.lang.OutOfMemoryError: Java heap space
这个异常是处理程序失败,产生Java堆内存溢出。

而且根据线程名,http-nio-9090-exec-19是在发生完NullPointerException,经过大约4分钟后发生堆内存溢出的异常。
解析完这些log后,再看看实际的程序运行背景:

在tomcat启动时,并未发生启动异常。tomcat服务器中有4个程序在同时运行,并不只有tug_ciimp这个程序,且这4个
程序毫无关联。在启动后,系统运行一切正常,当启动到第10天左右时候,产生内存溢出这个异常。第一次发生此异常
只是把tomcat重启,系统恢复正常运行。又间隔大约10多天时间又发生内存溢出。
为了把这个定时炸弹解决掉,准备采取以下措施,从网上找出内存溢出的可能情况:

1.java运行内存分配不足,启动参数内存值设定的过小。有几个地方:一是开发环境中eclipse.ini中,    
二是tomcat的启动文件中catalina.bat/catalina.sh中。因为不是开发环境,所以eclipse.ini去掉。    
2.代码中存在死循环或循环产生过多重复的对象实体。    
3.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;    
4.创建的对象持续增加,未得到及时清理,日积月累使内存溢出。    
5.一次性提取大量数据到内存的地方(10万数据以上)    
6.某个线程执行时间过长,那么就很危险了,占用的内存无法释放。容易造成内存的溢出。

总结完以上问题,需要重点排查以下几点:            
1.检查代码中是否有死循环或递归调用。            
2.检查是否有大循环重复产生新对象实体。            
3.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存            
溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有            
可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。            
4.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得            
这些对象不能被GC回收。            
有了以上这几点内存溢出的情况,不过根据实际背景分析出,基本不会是内存分配不足,如果内存分配有问题在启动            
时候就会报异常,所以先排除1之外剩余四点都有可能。根据项目实际使用情况,当前处于试运行阶段,出现一次性            
提取大量数据的可能性也不大,所以首先从2、3、4、5这几点着手,由于项目的代码很多,一个一个代码排查很笨拙            
所以先采取以下方案进行观察:
首先选择jvisualvm工具,来查看到堆内存中各个对象的数量以及占用的内存大小。    
如果找到有大量的自定义对象一直无法释放,可能距离定位到问题就不远了。

jvisualvm监测结果:

监测总览:

jvisualvm概述,如图DUMP必须调出来才能在内存溢出弹出错误信息:

通过jconsole监测结果,参数总览:

堆内存总览:

根据将近6天时间持续监测,发现cup、内存、类、线程等一直很平稳,没有持续升高现象,但是CPU偶尔会有突发性升高并会很快的下降回到正常。通过类实例数监测结果,对象所占内存也并不大。通过监测图还可看出,虽然结果运行比较平稳,但是通过检测工具发现堆初始值和最大值分别是128m和256m,并且离最大值比较近,所以突发的大数据量导致内存暴涨的可能性比较大。(本来水面离堤坝最高点比较接近的情况下又下了场大雨,导致决堤)

所以目前从两个方向去处理这个问题:

1.修改tomcat的内存参数,让内存参数加大。
2.减少应用中单次请求数据量过大的情况,比如,对数据查询时做分页处理,其它操作时也分批次。几个定时任务之间
不在同一时刻执行。(但是通过log发生时间,推断跟定时任务关系不大)
所以,先把内存参数调大,再观测一段时间。

由于在windows server服务器的tomcat是通过系统服务启动tomcat服务,所以在TOMCAT_HOME/bin/catalina.bat    
中添加是无效的,windows服务执行的是bin\tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置。    
所以,需要在注册表中进行修改,ctrl+R,输入regedit后,出现注册表,路径为:    
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\Tomcat8\Parameters\Java    
此路径下的Options    
经过尝试在Options的最下面加入     
-Xms128M    
-Xmx1024M    
并重启tomcat服务后,并不起作用,尝试在catalina.bat下添加:    
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "    
重启服务,以及重新安装tomcat系统服务还是不起作用。    
windows server重新安装tomcat系统服务步骤如下:    
CMD 命令进入到 Tomcat 的 bin 目录下,先停掉tomcat系统服务,执行service remove 服务名称    
再输入 service install 服务名称,再装载上tomcat系统服务,tomcat系统服务装配完毕后,    
进入tomcat的bin目录下,找到tomcat8w.exe,双击点开

在此处,把初始内存和最大内存更改后,加入jmx连接,并定义好连接端口12003(不要与其它服务冲突即可)            
-Dcom.sun.management.jmxremote.port=12003            
-Dcom.sun.management.jmxremote.ssl=false            
-Dcom.sun.management.jmxremote.authenticate=false            
用系统服务重启tomcat,然后启动jconsole和jvisualvm连接

自从更改完初始参数后,经过两个多月使用,没再发生内存溢出问题。


内存及GC 的相关参数

   内存相关设置(32位系统Heap 最大支持2GB,64位以上无限制)        
   -Xms:初始堆(Heap)大小,默认3670k。当空闲堆内存小于40%时,JVM 就会增大堆内存直到-Xmx 所设置的最大值,        
可以通过-XX:MinHeapFreeRatio=n 设置其比例。默认是物理内存的1/64。        
   -Xmx:最大堆(Heap)大小,默认64m。当空闲堆内存大于70%时,JVM 会减少堆内存直到-Xms 所设置的最小值,可        
以通过-XX:MaxHeapFreeRatio=n 设置其比例。默认是物理内存的1/4。        
   -Xmn:新生代大小,增大新生代后会相应减小老年代大小。此值对系统性能影响较大,Java 官方推荐配置为整个        
堆大小的3/8。        
   -Xss:设置每个线程栈的大小。Java1.5 以后每个线程栈默认大小为1M,之前每个线程栈默认大小为256K。        
可以根据应用的线程所需内存大小进行调整。一般情况下默认值已经能满足绝大部分情景的应用,如果想更进一步优化        
则需要非常细致的测试。在相同物理内存下,减小这个值能生成更多的线程,进程中可容纳线程数量与很多因素有关,        
感兴趣的可以详细了解下,据说可以达到6500个以上。        
   -XX:MinHeapFreeRatio=40:如果发现空闲堆内存占到整个预估上限值的40%,则增大上限值。        
   -XX:MaxHeapFreeRatio=70:如果发现空闲堆内存占到整个预估上限值的70%,则收缩预估上限值。        
   -XX:NewRatio=2:设置年轻代和老年代的比值。例如:n=3,则表示年轻代与老年代比值为1:3,年轻代占整个年        
轻代与老年代之和的1/4。        
   -XX:SurvivorRatio=8:Eden 与Survivor 的占用比例。例如8表示,一个survivor 区占用 1/8 的Eden 内存,        
即1/10的新生代内存,此处需注意年轻代有2个survivor 区,所以比例为1:10。        
   -XX:TargetSurvivorRatio=50:实际使用的survivor 空间大小占比。默认是47%,最高90%。        
   -XX:MaxPermSize=64m:设置持久代(即方法区)占整个堆内存的最大值。        
   -XX:MaxTenuringThreshold=0:设置对象最大年龄。即对象在在Eden 与Survivor 区之间被复制的次数,每        
被复制一次就增加1岁,默认值为15。如果设置为0的话,则Eden 中对象不经过Survivor 区直接进入老年代。        
Heap size 的大小是Young Generation 和Tenured Generaion 之和。        
注意1:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。        
注意2:Heap Size最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。        
Tomcat启动内存设置:        
如果需要对tomcat启动内存参数做设置,则修改TOMCAT_HOME/bin/catalina.bat,        
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:        
set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m        
或修改catalina.sh        
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:        
JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"        
另一种做法对tomcat容器,可以在启动时对jvm设置内存限度。对tomcat,可以在catalina.bat中添加:        
set CATALINA_OPTS=-Xms128M -Xmx256M        
set JAVA_OPTS=-Xms128M -Xmx256M        
或者把%CATALINA_OPTS%和%JAVA_OPTS%代替为-Xms128M -Xmx256M

堆内存和非堆内存                
“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在Java虚拟机启动时                
创建的。在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。                
简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理                
或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法                
的代码都在非堆内存中。                
JVM主要管理两种类型的内存:堆和非堆                
Heap memory Code Cache                
Eden Space                
Survivor Space                
Tenured Gen                
non-heap memory Perm Gen                
native heap?(I guess)                
堆内存                
Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在Java虚拟机启动                
时创建的。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。                
堆的大小可以固定,也可以扩大和缩小。堆的内存不需要是连续空间。                
非堆内存                
Java虚拟机管理堆之外的内存(称为非堆内存)。                
Java虚拟机具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和                
方法数据,以及方法和构造方法的代码。它是在 Java 虚拟机启动时创建的。                
方法区在逻辑上属于堆,但Java虚拟机实现可以选择不对其进行回收或压缩。与堆类似,方法区的大小可以固定,也                
可以扩大和缩小。方法区的内存不需要是连续空间。                
除了方法区外,Java虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。例如,JIT编译器需                
要内存来存储从Java虚拟机代码转换而来的本机代码,从而获得高性能。                
各区概念解释参照:                
https://www.cnblogs.com/kxm87/p/7205414.html                
https://blog.csdn.net/shiyong1949/article/details/52585256                
https://blog.csdn.net/zyc88888/article/details/80346409                
几个基本概念                
Heap space:存放Instance。                
Java Heap(堆)分为3个区:                
Eden Space(伊甸园)、Survivor Space(幸存者区)、Old Gen(老年代-养老区)                
Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象。                
Eden Space字面意思是伊甸园,对象被创建的时候首先放到这个区域,进行垃圾回收后,不能被回收的对象被放入                
到空的survivor区域。                
Survivor Space幸存者区,用于保存在Eden space内存区域中经过垃圾回收后没有被回收的对象。Survivor有两个,                
分别为To Survivor、 From Survivor,这个两个区域的空间大小是一样的。执行垃圾回收的时候Eden区域不能被                
回收的对象被放入到空的survivor(也就是To Survivor,同时Eden区域的内存会在垃圾回收的过程中全部释放),                
另一个survivor(即From Survivor)里不能被回收的对象也会被放入这个survivor(即To Survivor),然后                
To Survivor 和 From Survivor的标记会互换,始终保证一个survivor是空的。                
               
 Eden Space和Survivor Space都属于新生代,新生代中执行的垃圾回收被称之为Minor GC(因为是对新生代进                
行垃圾回收,所以又被称为Young GC),每一次Young GC后留下来的对象age加1。                
注:GC为Garbage Collection,垃圾回收。                
Old Gen老年代,用于存放新生代中经过多次垃圾回收仍然存活的对象,也有可能是新生代分配不了内存的大对象会                
直接进入老年代。经过多次垃圾回收都没有被回收的对象,这些对象的年代已经足够old了,就会放入到老年代。                
当老年代被放满的之后,虚拟机会进行垃圾回收,称之为Major GC。由于Major GC除并发GC外均需对整个堆进行扫描和回收,因此又称为Full GC。                
总结:heap区即堆内存,整个堆大小=年轻代大小 + 老年代大小。堆内存默认为物理内存的1/64(<1GB);默认空余                
堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制,可以通过MinHeapFreeRatio参数进行调整;默认空余堆内                
存大于70%时,JVM会减少堆直到-Xms的最小限制,可以通过MaxHeapFreeRatio参数进行调整。                
非heap区又分:                
Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。                
Code Cache代码缓存区,它主要用于存放JIT所编译的代码。CodeCache代码缓冲区的大小在client模式下默认最大                
是32m,在server模式下默认是48m,这个值也是可以设置的,它所对应的JVM参数为ReservedCodeCacheSize和                
InitialCodeCacheSize,可以通过如下的方式来为Java程序设置。                
-XX:ReservedCodeCacheSize=128m                
CodeCache缓存区是可能被充满的,当CodeCache满时,后台会收到CodeCache is full的警告信息,如下所示:                
“CompilerThread0” java.lang.OutOfMemoryError: requested 2854248 bytes for Chunk::new. Out of swap space?                
注:JIT编译器是在程序运行期间,将Java字节码编译成平台相关的二进制代码。正因为此编译行为发生在程序运行                
期间,所以该编译器被称为Just-In-Time编译器。                
Perm Gen全称是Permanent Generation space,是指内存的永久保存区域,因而称之为永久代。这个内存区域用                
于存放Class和Meta的信息,Class在被 Load的时候被放入这个区域。因为Perm里存储的东西永远不会被JVM垃圾                
回收的,所以如果你的应用程序LOAD很多CLASS的话,就很可能出现PermGen space错误。默认大小为物理内存的1/64。     
Perm Gen中放着类、方法的定义。持久代主要存放类定义、字节码和常量等很少会变更的信息。                
jvm Stack区域放着方法参数、局域变量等的引用,方法执行顺序按照栈的先入后出方式。                
HotSpot虚拟机GC算法采用分代收集算法:                
1、一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直到GC到来打破了他们平静                
的生活。GC会逐一问清楚每个对象的情况,有没有钱(此对象的引用)啊,因为GC想赚钱呀,有钱的才可以敲诈嘛。          
然后富人就会进入Survivor Space(幸存者区),穷人的就直接kill掉。                
2、并不是进入Survivor Space(幸存者区)后就保证人身是安全的,但至少可以活段时间。GC会定期(可以自定义)                
会对这些人进行敲诈,亿万富翁每次都给钱,GC很满意,就让其进入了Genured Gen(养老区)。万元户经不住几次敲诈             就没钱了,GC看没有啥价值啦,就直接kill掉了。                
3、进入到养老区的人基本就可以保证人身安全啦,但是亿万富豪有的也会挥霍成穷光蛋,只要钱没了,GC还是kill掉。              
分区的目的:新生区由于对象产生的比较多并且大都是朝生夕灭的,所以直接采用标记-清理算法。而养老区生命力很                
强,则采用复制算法,针对不同情况使用不同算法。

堆内存分配            
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;            
JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。            
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;            
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。            
因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。            
说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,            
不是Throwable的,无法用try…catch捕捉。            
非堆内存分配            
1.JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;            
2.由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。            
还有一说:MaxPermSize缺省值和-server -client选项相关,-server选项下默认MaxPermSize为64m,-client选项            
下默认MaxPermSize为32m。这个没有实验过。            
3. XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。            
4. 为什么会内存益出:            
这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance            
的Heap区域不同。            
GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,            
就很可能出现PermGen space错误。            
5. 这种错误常见在web服务器对JSP进行pre compile的时候。            
JVM内存限制(最大值)            
1. 首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。            
简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB            
(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。            
2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?            
通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于            
实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:            
 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;            
 -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理            
内存等等。说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,       
因为有一部分被硬件占用了。            
3.如果你有一个双核的CPU,也许可以尝试这个参数: -XX:+UseParallelGC让GC可以更快的执行(只是JDK5里对GC新增加的参数)            
4.如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。            
解决方法:设置MaxPermSize大小。            
增加服务器启动的JVM参数设置:            
 -Xms128m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m            
如tomcat,修改TOMCAT_HOME/bin/catalina.sh,在echo“Using CATALINA_BASE: $CATALINA_BASE”上面            
加入以下行:            
JAVA_OPTS=”-server -XX:PermSize=64M -XX:MaxPermSize=128m            
5. 建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存            
补充说明:            
PermSize和MaxPermSize指明虚拟机为java永久生成对象(Permanate generation)如,class对象、方法对象这些            
可反射(reflective)对象分配内存限制,这些内存不包括在Heap(堆内存)区之中。            
MaxPermSize缺省值和-server -client选项相关:-server选项下默认MaxPermSize为64m、-client选项下默认            
MaxPermSize为32m。            
申请一块内存的过程            
1.JVM会试图为相关Java对象在Eden中初始化一块内存区域            
2.当Eden空间足够时,内存申请结束。否则到下一步            
3.JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收);释放后若Eden空间仍然不足以放入            
新对象,则试图将部分Eden中活跃对象放入Survivor区/OLD区            
4.Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会            
被保留在Survivor区。            
5.当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)            
6.完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象            
创建内存区域,则出现”out of memory错误”            
内存回收算法            
Java中有四种不同的回收算法,对应的启动参数为:            
 –XX:+UseSerialGC            
 –XX:+UseParallelGC            
 –XX:+UseParallelOldGC            
 –XX:+UseConcMarkSweepGC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戰士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值