关于JAVA中内存溢出的解决办法

时间:2022-09-21 17:06:53
见博客 http://blog.csdn.net/czp0608/article/details/7352024
关于JAVA中内存溢出的解决办法
J2ee应用系统是运行在J2EE应用服务器上的,而j2ee应用服务器又是运行在JVM上的,
生成环境中JVM参数的优化和设置对于J2EE应用系统性能有着决定性的作用。要优化系统,则需要对JVM参数进行合理的设置,所以我们需要了解究竟在什么地方进行设置、有哪些参数以及各参数的意义分别是什么,并且我们还得了解JVM的内存管理机制究竟是个什么玩意儿?其实我们在网上搜索引擎上,一搜就有可以获取到一大把相关信息,关键是我们如何深入的理解它们。那么下面我们就简单的介绍一下究竟什么是JVM的内存管理机制吧~!   
 
JVM的早期版本并没有进行分区管理;这样的后果是JVM进行垃圾回收时,不得不扫描JVM所管理的整片内存,所以搜集垃圾是很耗费资源的事情,也是早起JAVA程序的性能低下的主要原因。随着JVM的发展,JVM引进了分区管理的机制。

JVM所管理的所有内存资源分为2个大的部分。永久存储区(Permanent Space) 和堆空间(The Heap Space)。其中对空间又分为新生区()和养老区,新生区又分为伊甸园,幸存者0区、幸存1区。如下图:

关于JAVA中内存溢出的解决办法

关于个分区的用途,大家可以参考其他相关文档。本教程所要处理的问题是如何解决内存溢出的问题。接下来以tomcat服务器为例:
我们首先得找到内存管理所要设置的参数在哪个文件:<CATALINA_HOME>/bin/catalina.bat。
需要添加一行代码:
JAVA_OPTS="-Xms512m -Xmx512m -Xss1024K -XX:PermSize=256m -XX:MaxPermSize=256m"
下面分别对各参数进行介绍和解释:
JVM 相关参数:
参数名参数说明
-server 启用能够执行优化的编译器, 显著提高服务器的性能,但使用能够执行优化的编译器时,服务器的预备时间将会较长。生产环境的服务器强烈推荐设置此参数。
-Xss 单个线程堆栈大小值;JDK5.0 以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000 左右。
-XX:+UseParNewGC 可用来设置年轻代为并发收集【多CPU】,如果你的服务器有多个CPU,你可以开启此参数;开启此参数,多个CPU 可并发进行垃圾回收,可提高垃圾回收的速度。此参数和+UseParallelGC,-XX:ParallelGCThreads 搭配使用。
+UseParallelGC 选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。可提高系统的吞吐量。
-XX:ParallelGCThreads 年轻代并行垃圾收集的前提下(对并发也有效果)的线程数,增加并行度,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。永久存储区相关参数:参数名参数说明
-Xnoclassgc 每次永久存储区满了后一般GC 算法在做扩展分配内存前都会触发一次FULL GC,除非设置了-Xnoclassgc.
-XX:PermSize 应用服务器启动时,永久存储区的初始内存大
-XX:MaxPermSize 应用运行中,永久存储区的极限值。为了不消耗扩大JVM 永久存储区分配的开销,将此参数和-XX:PermSize 这个两个值设为相等。堆空间相关参数参数名参数说明
-Xms 启动应用时,JVM 堆空间的初始大小值。
-Xmx 应用运行中,JVM 堆空间的极限值。为了不消耗扩大JVM 堆控件分配的开销,将此参数和-Xms 这个两个值设为相等,考虑到需要开线程,讲此值设置为总内存的80%.
-Xmn 此参数硬性规定堆空间的新生代空间大小,推荐设为堆空间大小的1/4。
上面所列的JVM 参数关系到系统的性能,而其中-XX:PermSize,
-XX:MaxPermSize,-Xms,-Xmx 和-Xmn 这5 个参数更是直接关系到系统的性能,系统是否会出现内存溢出。
-XX:PermSize 和-XX:MaxPermSize 分别设置应用服务器启动时,永久存储区的初始大小和极限大小;在生成环境中强烈推荐将这个两个值设置为相同的值,以避免分配永久存储区的开销,具体的值可取系统“疲劳测试”获取到的永久存储区的极限值;如果不进行设置-XX:MaxPermSize 默认值为64M,一般来说系统的类定义文件大小都会超过这个默认值。
-Xms 和-Xmx 分别是服务器启动时,堆空间的初始大小和极限值。-Xms 的默认值是物理内存的1/64 但小于1G,-Xmx 的默认值是物理内存的1/4 但小于1G.在生产环境中这些默认值是肯定不能满足我们的需要的。也就是你的服务器有8g 的内存,不对JVM 参数进行设置优化,应用服务器启动时还是按默认值来分配和约束JVM 对内存资源的使用,不会充分的利用所有的内存资源。

结论:“永久存储区溢出(java.lang.OutOfMemoryError: Java Permanent Space)”乃是永久存储区设置太小,不能满足系统需要的大小,此时只需要调整-XX:PermSize 和-XX:MaxPermSize 这两个参数即可。“JVM 堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM 堆空间不足,此时只需要调整-Xms 和-Xmx 这两个参数即可。

到此我们知道了,当系统出现内存溢出时,是哪些参数设置不合理需要调整。但我们怎么知道服务器启动时,到底JVM 内存相关参数的值是多少呢?
这个问题其实Sun公司早已经意料到了,所以给我们开发了内存使用监控工具jvmstat.
大家可以到ORACLE官网进行下载。用它可以很方便的看到我们的服务器内存使用情况。
将下载的jvmstat包解压到如“C:\Program Files\Java\jvmstat”(这是我本地java路径,大家可以根据自己所安装的java环境的路径进行解压)。启动完之后我们就可以使用visualgc命令了,cmd进入命令符窗口,输入tasklist(windows下查看进程任务PID)查找到你要检测进程PID.然后直接输入visuglgc PID 就会弹出三个可见视图。
如下图:
 
关于JAVA中内存溢出的解决办法

参考资料《浅谈SUN JVM 内存管理与应用服务器的优化之SUN JVM 内存管理》Jason S.H.Chen
参考资料《浅谈SUN JVM 内存管理与应用服务器的优化之服务器内存分配与优化》Jason S.H.Chen

48 个解决方案

#1


该回复于2012-03-14 16:51:37被版主删除

#2


图片咋弄出来了 ~谢谢了 呵呵

#3


该回复于2012-03-16 09:07:54被版主删除

#4


该回复于2012-03-16 11:33:51被版主删除

#5


你这图片那弄的?

#6


上传的

#7


还能上图啊 奇迹

#8


真受教啦~

#9


该回复于2012-03-16 13:05:33被版主删除

#10


每个帖子都得回  一个不可以落下啊  顶LZ啊 

#11


图片不错,支持

#12


引用 5 楼 zl3450341 的回复:
你这图片那弄的?

上面的是自己画的,下面的是jvmstat给弄出来的~

#13


该回复于2012-03-16 16:20:16被版主删除

#14


了解一下.

#15


该回复于2012-03-16 16:28:47被版主删除

#16


该回复于2012-03-16 16:53:20被版主删除

#17


谢谢分享,支持一下!

#18


查看性能很强大吗

#19


引用 17 楼 maco_wang 的回复:
谢谢分享,支持一下!
。。

#20


该回复于2012-03-19 09:25:27被版主删除

#21


顶楼主  楼主又散分又分享技术无私精神令人感动

#22


该回复于2012-03-19 09:24:07被版主删除

#23


该回复于2012-03-19 09:22:52被版主删除

#24


nice

#25


该回复于2012-03-19 09:15:49被版主删除

#26


关于JAVA中内存溢出的解决办法学习一下

#27


该回复于2012-03-19 09:07:22被版主删除

#28


该回复于2012-03-19 09:45:35被版主删除

#29


该回复于2012-03-19 09:40:28被版主删除

#30


该回复于2012-03-19 11:54:21被版主删除

#31


支持楼主

#32


该回复于2012-03-19 09:36:21被版主删除

#33


很高深 小弟受教啦

#34


呵呵!楼主给力,收藏了。

#35


该回复于2012-03-19 08:56:41被版主删除

#36


学习一下,感谢楼主

#37


该回复于2012-03-19 17:00:57被版主删除

#38


该回复于2012-03-19 22:38:05被版主删除

#39


好帖! 顶下

#40


关于JAVA中内存溢出的解决办法

#41


该回复于2012-03-28 14:25:18被版主删除

#42


你这篇文章写得忑简单了吧,这样就可以完全避免JAVA内存益处?
JAVA环境那么复杂,在具体情况下是要具体分析的.

#43


引用 42 楼  的回复:
你这篇文章写得忑简单了吧,这样就可以完全避免JAVA内存益处?
JAVA环境那么复杂,在具体情况下是要具体分析的.

嗯,明白 这也当时抛砖引玉啦,大家可以把自己的看法和高见提出来供大家一同学习,不是很好嘛~

#44


过来学习! 关于JAVA中内存溢出的解决办法

#45


过来学习下,最近遇到了一个总是溢出的问题 关于JAVA中内存溢出的解决办法

#46


关于JAVA中内存溢出的解决办法

#47


关于JAVA中内存溢出的解决办法

#48


高大上啊 关于JAVA中内存溢出的解决办法

#1


该回复于2012-03-14 16:51:37被版主删除

#2


图片咋弄出来了 ~谢谢了 呵呵

#3


该回复于2012-03-16 09:07:54被版主删除

#4


该回复于2012-03-16 11:33:51被版主删除

#5


你这图片那弄的?

#6


上传的

#7


还能上图啊 奇迹

#8


真受教啦~

#9


该回复于2012-03-16 13:05:33被版主删除

#10


每个帖子都得回  一个不可以落下啊  顶LZ啊 

#11


图片不错,支持

#12


引用 5 楼 zl3450341 的回复:
你这图片那弄的?

上面的是自己画的,下面的是jvmstat给弄出来的~

#13


该回复于2012-03-16 16:20:16被版主删除

#14


了解一下.

#15


该回复于2012-03-16 16:28:47被版主删除

#16


该回复于2012-03-16 16:53:20被版主删除

#17


谢谢分享,支持一下!

#18


查看性能很强大吗

#19


引用 17 楼 maco_wang 的回复:
谢谢分享,支持一下!
。。

#20


该回复于2012-03-19 09:25:27被版主删除

#21


顶楼主  楼主又散分又分享技术无私精神令人感动

#22


该回复于2012-03-19 09:24:07被版主删除

#23


该回复于2012-03-19 09:22:52被版主删除

#24


nice

#25


该回复于2012-03-19 09:15:49被版主删除

#26


关于JAVA中内存溢出的解决办法学习一下

#27


该回复于2012-03-19 09:07:22被版主删除

#28


该回复于2012-03-19 09:45:35被版主删除

#29


该回复于2012-03-19 09:40:28被版主删除

#30


该回复于2012-03-19 11:54:21被版主删除

#31


支持楼主

#32


该回复于2012-03-19 09:36:21被版主删除

#33


很高深 小弟受教啦

#34


呵呵!楼主给力,收藏了。

#35


该回复于2012-03-19 08:56:41被版主删除

#36


学习一下,感谢楼主

#37


该回复于2012-03-19 17:00:57被版主删除

#38


该回复于2012-03-19 22:38:05被版主删除

#39


好帖! 顶下

#40


关于JAVA中内存溢出的解决办法

#41


该回复于2012-03-28 14:25:18被版主删除

#42


你这篇文章写得忑简单了吧,这样就可以完全避免JAVA内存益处?
JAVA环境那么复杂,在具体情况下是要具体分析的.

#43


引用 42 楼  的回复:
你这篇文章写得忑简单了吧,这样就可以完全避免JAVA内存益处?
JAVA环境那么复杂,在具体情况下是要具体分析的.

嗯,明白 这也当时抛砖引玉啦,大家可以把自己的看法和高见提出来供大家一同学习,不是很好嘛~

#44


过来学习! 关于JAVA中内存溢出的解决办法

#45


过来学习下,最近遇到了一个总是溢出的问题 关于JAVA中内存溢出的解决办法

#46


关于JAVA中内存溢出的解决办法

#47


关于JAVA中内存溢出的解决办法

#48


高大上啊 关于JAVA中内存溢出的解决办法