JVM调优

目录

①堆大小的设置;②回收器的选择;③打印GC日志。

参数设置示例:

当一组对象生成时,内存申请过程如下:

OOM(Out Of Memory)异常一般主要有如下2种原因:


①堆大小的设置;②回收器的选择;③打印GC日志。

调优手段主要是通过 控制堆内存的各个部分的比例GC策略 来实现的,下面来看看设置不合理会导致什么后果。

1)新生代设置过小

新生代GC次数非常频繁,增大系统消耗;导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC

2)新生代设置过大

新生代设置过大会导致旧生代过小(堆总量是一定的),从而诱发Full GC;新生代GC耗时大幅度增加。一般来说新生代占整个堆1/3比较合适

3)Survivor设置过小

导致对象从eden直接到达旧生代,降低了在新生代的存活时间

4)Survivor设置过大

导致eden过小,增加了GC频率(eden满,GC;Survivor满,不诱发GC)。另外,通过-XX:MaxTenuringThreshold = n 来控制新生代存活时间,尽量让对象在新生代被回收

由内存管理和垃圾回收可知,新生代和旧生代有多种GC策略和组合搭配,对开发来说是个难题,JVM提供了两种较为简单的GC策略的设置方式。

1)吞吐量优先

JVM以吞吐量为指标,由-XX:GCTimeRatio = n来设置

2)暂停时间优先

JVM以暂停时间为指标,由-XX:MaxGCPauseRatio = n来设置

参数设置示例:

-Xmn2g:设置年轻代大小为2G。在整个堆内存大小确定的情况下,增大年轻代会减小年老代,反之亦然。

-XX:MaxTenuringThreshold = 7(Threshold n门槛,阈):表示一个对象如果在Survivor区,移动了7次还没有被垃圾回收就进入老年代。如果设置为0,则年轻代对象不经过Survivor区,直接进入年老代,对于需要大量常住内存的应用,这样做可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代存活时间,增加对象在年轻代被垃圾回收的概率,减少Full GC的频率,可以在某种程度上提高服务器的稳定性。

年轻代:Eden + Survivor(from)+ Survivor(to)

              垃圾回收:GC

年老代:在年轻代中经历了N次(可配置)垃圾回收后仍然存活的对象,就会被复制到年老代。因此,可以认为年老代中存放的                都是一些生命周期较长的对象。

              垃圾回收:Full GC

持久代:用于存放静态类型数据,如:Java class、Method等。持久代对垃圾回收没有显著影响。

当一组对象生成时,内存申请过程如下:

①JVM会试图为相关Java对象在年轻代的Eden区中初始化一块内存区域。

②当Eden区空间足够时,内存申请结束。否则,执行下一步。

③JVM试图释放在Eden区中所有不活跃的对象(Young GC)。释放后若Eden空间仍然不足以放入新对象,JVM则试图将部分Eden区中的活跃对象放入Survivor区。

④Survivor区被用来作为Eden区及年老代的中间交换区域。当年老代空间足够时,Survivor区中存活了一定次数的对象会被转移到年老代。

⑤当年老代空间不够时,JVM会在年老代进行完全的垃圾回收(Full GC)。

⑥Full GC后,若Survivor区及年老代仍然无法存放从Eden区复制过来的对象,则会导致JVM无法再Eden区为新生成的对象申请内存,即出现OOM,即Out Of Memory

OOM(Out Of Memory)异常一般主要有如下2种原因:

①年老代溢出,表现为java.lang.OutOfMemoryError:Javaheapspace

这是最常见的情况,产生原因是:设置的内存参数Xmx过小或程序的内存泄露及使用不当问题。

例如:循环上万次的字符串处理、创建上千万个对象、在一段代码内申请上百M甚至上G的内存。还有的时候虽然不会报内存溢出,却会使系统不间断的垃圾回收,也无法处理其他请求。这种情况下除了检查程序、打印堆内存等方法排查,还可以借助一些内存分析工具,如:MAT

②持久代溢出,表现为java.lang.OutOfMemoryError:PermGenspace

通常是由于持久代设置过小,动态加载了大量Java类而导致溢出,解决方法为由将参数-XX:MaxPermSize调大(一般245M能满足绝大多数应用程序需求)。将部分Java类放到容器共享区(例如:Tomcat share lib)去加载的办法也是一个思路,但前提是容器里部署了多个应用,且这些应用有大量的共享类库。

以上知识是Jdk1.8以前,Jdk1.8去除了Perm持久区。

 

 --------------------------------------------以上内容节选自《深入分析Java Web技术内幕》一书

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值