论坛首页 Java企业应用论坛

浅谈SUN JVM内存管理与应用服务器的优化之 服务器内存分配与优化

浏览 14979 次
精华帖 (0) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (5)
作者 正文
   发表时间:2009-12-18   最后修改:2009-12-23
作者:Jason S.H.Chen

上篇(http://cshbbrain.iteye.com/blog/526356)给大家介绍了SUN JVM的内存管理机制。本篇主要讲解与性能相关的JVM参数,怎样使用工具监控JVM的内存分配使用情况和怎样调整JVM参数让系统在特定硬件配置下达到最优化的性能。
通过上篇SUN JVM内存管理机制的介绍,大家都知道了SUN JVM内存分为永久存储区,伊甸园,幸存者0区,幸存者1区和养老区等几个区域。他们的作用以及垃圾回收处理过程在上篇也做了详细介绍。下面我们就来看看和这些内存分区相关的JVM参数。

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对内存资源的使用,不会充分的利用所有的内存资源。
到此我们就不难理解上文提到的“我的服务器有8g内存,系统也就100M左右,居然出现内存溢出”这个“怪现象”了。在上文我曾提到“永久存储区溢出(java.lang.OutOfMemoryError: Java Permanent Space)”和“JVM堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”这两种溢出错误。现在大家都知道答案了:“永久存储区溢出(java.lang.OutOfMemoryError: Java Permanent Space)”乃是永久存储区设置太小,不能满足系统需要的大小,此时只需要调整-XX:PermSize和-XX:MaxPermSize这两个参数即可。“JVM堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM堆空间不足,此时只需要调整-Xms和-Xmx这两个参数即可。
到此我们知道了,当系统出现内存溢出时,是哪些参数设置不合理需要调整。但我们怎么知道服务器启动时,到底JVM内存相关参数的值是多少呢。在实践中,经常遇到对JVM参数进行设置了,并且自己心里觉得应该不会出现内存溢出了;但不幸的是内存溢出还是发生了。很多人百思不得其解,那我可以肯定地告诉你,你设置的JVM参数并没有起作用(本文咱不探讨没有起作用的原因)。不信我们就去看看,下面介绍如何使用SUN公司的内存使用监控工具jvmstat.
本文只介绍如何使用jvmstat查看内存使用,不介绍其安装配置。有兴趣的读者,可到SUN公司的官方网站下载一个,他本身已经带有非常详细的安装配置文档了。这里假设你已经在你的应用服务器上配置好了jvmstat了。那我们就开始使用他来看看我们的服务器到底是有没有按照我们设置的参数启动。
首先启动服务器,等服务器启动完。开启DOS窗口(此例子是在windows下完成,linux下同样),在dos窗口中输入jps这个命令。如下图



窗口中会显示所有JAVA应用进程列表,列表的第一列为应用的进程ID,第二列为应用的名字。在列表中找到你的应用服务器的进程ID,比如我这里的应用服务器进程ID为1856.在命令行输入visualgc 1856回车。进入jvmstat的主界面,如下图:



上图分别标注了伊甸园,幸存者0区,幸存者1区,养老区和永久存储区。图上直观的反应出各存储区的大小,已经使用的大小,剩下的空间大小,并用数字标出了各区的大小;如果你这上面的数字和你设置的JVM参数相同的话,那么恭喜你,你设置的参数已经起作用,如果和你设置的不一致的话,那么你设置的参数没有起作用(可能是服务器的启动方式没有载入你的JVM参数设置。)
在优化服务器的时候,这个工具很有用,他占用资源少。可以随应用服务器一直保持开启状态,如果系统发生内粗溢出,可以一眼就看出是那个区发生了溢出。根据观察结果进行进一步优化。
  • 大小: 34.7 KB
  • 大小: 154.5 KB
   发表时间:2009-12-18  
发到这个上面格式全没啦,郁闷。
0 请登录后投票
   发表时间:2009-12-19  
整理一下,这看着太费劲
0 请登录后投票
   发表时间:2009-12-20  
稍微调整了格式。
0 请登录后投票
   发表时间:2009-12-21  
   楼主是转帖的帖子吧。这篇文章基本都对,不过还是存在一些问题的。列出来给大家参考下:
1.  -Xss 单个线程堆栈大小值;JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
   很少有建议去减小这个值,只有在运行的java程序处理及大量低代销的任务线程时(如消息引擎的分发),否则 如果该值过小,它是会容易抛出StackOverFlowException的,实际情况是一般是限制最大值(比如linux系统建议为2M)。另外,线程堆栈的内存需求是独立在heap外的,如果所谓经验值在3000-5000,这种线程处理的内存需求就和文章下面建议heap为80%是相矛盾的。至于3000-5000在没有说明硬件环境和操作系统环境,也不考虑线程具体做什么事时,有点瞎蒙的意味。
2. -Xmx 应用运行中,JVM堆空间的极限值。为了不消耗扩大JVM堆控件分配的开销,将此参数和-Xms这个两个值设为相等,考虑到需要开线程,讲此值设置为总内存的80%.  总内存是多少啊?在拥有十多G内存的服务器上依然如此?32位的JVM能访问的内存不过2G多(与操作系统以及JVM实现有关)。

   其他的还没写完,下班了,回家补充点。
1 请登录后投票
   发表时间:2009-12-21   最后修改:2009-12-21
楼主 写道
-XX:+UseParNewGC 可用来设置年轻代为并发收集【多CPU】,如果你的服务器有多个CPU,你可以开启此参数;开启此参数,多个CPU可并发进行垃圾回收,可提高垃圾回收的速度。此参数和+UseParallelGC,-XX:ParallelGCThreads搭配使用。


这个参数的描述不正确。

引用
This flag turns on parallel garbage collection in the young generation. It can be enabled together with the CMS collector in the old generation.



楼主 写道
-Xnoclassgc 每次永久存储区满了后一般GC算法在做扩展分配内存前都会触发一次FULL GC,除非设置了-Xnoclassgc.
这个和fullgc应该也没有关系吧,fullgc是指yong和old都执行的gc,执行fullgc的使用jvm会产生停顿,这个参数只是控制是否开启perm区的gc,原来我发现这个值默认是关闭,但是jdk1.6里这个功能默认是开启了
1 请登录后投票
   发表时间:2009-12-21   最后修改:2009-12-22
凤舞凰扬 写道
   楼主是转帖的帖子吧。这篇文章基本都对,不过还是存在一些问题的。列出来给大家参考下:
1.  -Xss 单个线程堆栈大小值;JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
   很少有建议去减小这个值,只有在运行的java程序处理及大量低代销的任务线程时(如消息引擎的分发),否则 如果该值过小,它是会容易抛出StackOverFlowException的,实际情况是一般是限制最大值(比如linux系统建议为2M)。另外,线程堆栈的内存需求是独立在heap外的,如果所谓经验值在3000-5000,这种线程处理的内存需求就和文章下面建议heap为80%是相矛盾的。至于3000-5000在没有说明硬件环境和操作系统环境,也不考虑线程具体做什么事时,有点瞎蒙的意味。
2. -Xmx 应用运行中,JVM堆空间的极限值。为了不消耗扩大JVM堆控件分配的开销,将此参数和-Xms这个两个值设为相等,考虑到需要开线程,讲此值设置为总内存的80%.  总内存是多少啊?在拥有十多G内存的服务器上依然如此?32位的JVM能访问的内存不过2G多(与操作系统以及JVM实现有关)。

   其他的还没写完,下班了,回家补充点。

首先谢谢 凤舞凰扬,此文却为本人原创;此篇和(http://cshbbrain.iteye.com/blog/526356)为姊妹篇。有兴趣可到我的博客去看上篇。上篇本人发表在公司内刊之后,公司的人约我写下篇。由于本人此段时间较忙,匆匆写完,有些细节的地方还不曾仔细推敲。
0 请登录后投票
   发表时间:2009-12-22  
   呵呵,其实写写挺不错的,也是经验的总结。可以多交流下
0 请登录后投票
   发表时间:2009-12-22  
      看楼主既然在写关于JVM文章,就提供一个附件给楼主参考,也算交流吧。附件是我给部门做JVM的介绍的PPT,其中有一些内容也可以说明楼主文中一些相对不完善的地方,包括对于OutOfMemoryError的解释。
      另外楼主推荐的jvmstat只是一个对于JVM信息状态反馈的工具,对于JVM的优化起不了太多作用。另外,这种工具只适合于非生产环境,在生产环境一般是不会允许执行的。
      对于如何进行应用程序在application和JVM级别的调优,改天我写点东东...
1 请登录后投票
   发表时间:2009-12-23  
看了下你的ppt,对jvm讲得挺全面的。很期待你的文章。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics