JVM性能调优解决方案Word文档格式.docx
《JVM性能调优解决方案Word文档格式.docx》由会员分享,可在线阅读,更多相关《JVM性能调优解决方案Word文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
![JVM性能调优解决方案Word文档格式.docx](https://file1.bdocx.com/fileroot1/2022-10/13/863f357f-62cc-4d26-bdfc-816cf3cb08e8/863f357f-62cc-4d26-bdfc-816cf3cb08e81.gif)
量计算。
可靠性(reliability)
换句话说,我们想对更多的用户提供更快捷的、不会中断的服务。
JVM,性能调优的重点
JVM的性能调优的重点是垃圾回收(gc,garbagecollection)和内存管理垃圾回收的时候会导致整个虚拟机暂停服务,因此,应该尽可能地缩短垃圾回收的处理时间。
JVM内存
JVM占用的内存称为堆(heap),它被分为三个区:
年轻(young,又称为门6葡、老(tenured,又称为old)和永生(perm)。
这三个区是按照java对象的生存期划分的,在new区的对象生存期最短,很快就会被gc回收;
perm区的对象生存期最长,与JVM同生死。
Perm区的对象不会被gc回收。
new区又被分为三个部分:
伊甸园(eden)和两个幸存者(survivor)。
对象的创建总是在eden部分(这大概就是命名该部分为eden的原因吧)。
两个survivor中总有一个是空的,它作为另一个survivor的缓冲区。
当gc发生时,所有eden和survivor中活下来的对象被移动到另一个survivor中。
对象会在两个survivor之间不断移动,直到活得足够久,然后移动到old区。
我们可以
猜想,之所以如此划分使用内存,肯定是为了缩短gc的执行时间,提高gc的执行效率。
垃圾回收算法
除了默认的垃圾回收算法外,JVM还提供了两个:
并行(parallel)和并发(concurrent),前者作用在new区,后者作用在old区。
两者可以同时使用。
并行算法会产生多个线程以提高执行效率。
当有多个cpu的时候,它会显著
缩短gc的工作时间。
并发算法可以在JVM不中断对应用的服务的情况下执行(通常情况下,在gc
工作的时候JVM停止对应用的服务)。
】、性能参数
参数
含义
说明
-Xms
Heap的最小尺寸
-Xmx
Heap的最大尺寸
作为一个通行的准则,设置Xms和Xmx的尺寸一样,以减少gc的次数。
要将它们设置足够大,否则就会产生outofmemory错误,但又不能设置过大,过大会增加gc的工作时间。
-Xmn
new的尺寸
-XX:
PermSize
Perm的最小尺寸
MaxPermSize
Perm的最大尺寸
类似heap的设置,应该
将perm设置为固疋尺寸,即最大和最小尺寸一样。
SurvivorRatio
New区中eden与
Survivor区的比值
+UseParallelGC
使用parallelgc
ParallelGCThreads
Parallelgc的线程个数
与cpu个数相同,使得所有cpu都参与gc工作。
JVM的参数主要由-X和-XX类型的选项组成,上边列出了一些对内存和gc
的性能影响比较大的。
三、性能参数调优
要调整参数首先要观察它们。
观察JVM内存和gc的工具很多,jdk本身也提供了一些,这些工具简单、实用,而且不需要安装。
其中,最常用的是jps和
jstat,前者用来查看JVM的进程id(pid),后者用这个pid作为参数来得到内存和gc的状态,就是说,在执行jstat之前必须用jps得到JVM的pid。
Jstat的例子:
:
jstat-gcutil2130825010
其中,21308是(运行jboss)的JVM的pid;
250是采样间隔,单位是毫秒,即250毫秒采集一次数据;
10是采样次数。
上述命令的执行结果如下:
S0
S1
EO
P
YGCYGCTFGCFGCTGCT
0.00
135.081
11.39
5.29
13.57
328
1.955
327
133.126
列标题
Survivor
E
Eden
O
Old
Perm
以上数据都是百分比。
YGC
Young(new)区完成的gc的次数
YGCT
YGC消耗的总时间(秒)
FGC
整个heap完成的gc的次数
如果采用了
parallelgc,你会
看到YGC明显大于
FGCT
FGQ肖耗的总时间(秒)
GCT
YGCT-FGCT
我们可以将采样次数设置足够大,这样就可以看到内存和gc的变化了
从上述数据可以看出,内存各区域的占用率都不高,gc的执行时间都不长,不过,perm区有些太大,太浪费了。
因为perm区的对象与JVM的生命周期是-样的,对象数量不会动态变化,所以,我们可以把这个区域的尺寸设置为原尺寸的二分之一,这样,perm的占用率将从13%左右增加到26%左右。
从上述数据还可以看出,new区的gc明显比真个heap的gc快得多。
通常,FGC应该不超过400毫秒,否则,将严重影响java应用的正常运行。
分割线
一、JVM内存模型及垃圾收集算法
1.根据Java虚拟机规范,JVM将内存划分为:
*New(年轻代)
*Tenured(年老代)
*永久代(Perm)
其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:
3G)指定的内存中分配,Perm不属于堆内存,有虚拟机直接分配,但可以通过
PermSize-XX:
MaxPermSize等参数调整其大小。
•年轻代(NeW:
年轻代用来存放JVM刚分配的Java对象
*年老代(Tenured):
年轻代中经过垃圾回收没有回收掉的对象将被Copy
到年老代
•永久代(Perm):
永久代存放Class、Method元信息,其大小跟项目的规模、类、方法的量有关,一般设置为128M就足够,设置原则是预留30%
的空间。
New又分为几个部分:
*Eden:
Eden用来存放JVM刚分配的对象
*Survivor1
*Survivro2:
两个Survivor空间一样大,当Eden中的对象经过垃圾回收没有被回收掉时,会在两个Survivor之间来回Copy,当满足某个条件,
比如Copy次数,就会被Copy到Tenured。
显然,Survivor只是增加了对象在年轻代中的逗留时间,增加了被垃圾回收的可能性。
2.垃圾回收算法
垃圾回收算法可以分为三类,都基于标记-清除(复制)算法:
•Serial算法(单线程)
.并行算法
.并发算法
JVM会根据机器的硬件配置对每个内存代选择适合的回收算法,比如,如果机器多于1个核,会对年轻代选择并行算法,关于选择细节请参考JVM调优文档,
稍微解释下的是,并行算法是用多线程进行垃圾回收,回收期间会暂停程序的执行,而并发算法,也是多线程回收,但期间不停止应用执行。
所以,并发算法适用于交互性高的一些程序。
经过观察,并发算法会减少年轻代的大小,其实就是使用了一个大的年老代,这反过来跟并行算法相比吞吐量相对较低。
还有一个问题是,垃圾回收动作何时执行?
•当年轻代内存满时,会引发一次普通GC该GC仅回收年轻代。
需要强调的时,年轻代满是指Eden代满,Survivor满不会引发GC
*当年老代满时会引发FullGC,FullGC将会同时回收年轻代、年老代*当永久代满时也会引发FullGC,会导致Class、Method元信息的卸载
另一个问题是,何时会抛出OutOfMemoryException,并不是内存被耗空的时候才抛出
*JVM98的时间都花费在内存回收
•每次回收的内存小于2%
满足这两个条件将触发OutOfMemoryException,这将会留给系统一个微小的间隙以做一些Down之前的操作,比如手动打印HeapDump
二、内存泄漏及解决方法
1.系统崩溃前的一些现象:
«
每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4、5s
・FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC
*年老代的内存越来越大并且每次FullGC后年老代没有内存被释放
之后系统会无法响应新的请求,逐渐到达OutOfMemoryError的临界值。
2.生成堆的dump文件
通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件。
3.分析dump文件
下面要考虑的是如何打开这个3G的堆信息文件,显然一般的Window系统没有这么大的内存,必须借助高配置的Linux。
当然我们可以借助X-Window把Linux上的图形导入到Window。
我们考虑用下面几种工具打开该文件:
1.VisualVM
2.I