博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UseAdaptiveSizePolicy与CMS垃圾回收同时使用导致的JVM报错
阅读量:7049 次
发布时间:2019-06-28

本文共 2342 字,大约阅读时间需要 7 分钟。

   系统在灰度环境上变更时发现JVM启动报错,详细检查JVM配置参数,发现新境了如下配置:

   -XX:+UseAdaptiveSizePolicy和-XX:+UseConcMarkSweepGC

   初步猜想是JVM参数配置的问题,于是通过jmap -heap查看系统堆栈使用情况,如下:

Heap Configuration:     MinHeapFreeRatio = 40     MaxHeapFreeRatio = 70     MaxHeapSize      = 10737418240 (10240.0MB)     NewSize          = 2147483648 (2048.0MB)     MaxNewSize       = 2147483648 (2048.0MB)     OldSize          = 5439488 (5.1875MB)     NewRatio         = 2     SurvivorRatio    = 4     PermSize         = 21757952 (20.75MB)     MaxPermSize      = 134217728 (128.0MB)  Heap Usage:  unknown generation type:     capacity = 0 (0.0MB)     used     = 0 (0.0MB)     free     = 0 (0.0MB)     NaN% used  unknown generation type:     capacity = 0 (0.0MB)     used     = 0 (0.0MB)     free     = 0 (0.0MB)     NaN% used  Perm Generation:     capacity = 60878848 (58.05859375MB)     used     = 37927152 (36.17015075683594MB)     free     = 22951696 (21.888442993164062MB)     62.29939173619054% used

从打印的堆栈信息上看已发现异常

一、JVM分析

1、源码查看

  分析jdk的management.cpp代码,发现在计算堆内存区大小的时候,对commit都进行了累加,但是在max_size没有定义(无效,从MemoryPool获取)的情况下,total_max没有累加,导致commited比max大。

  修复后的代码见:  的方法JVM_ENTRY中。 

 对比: 

   原来只处理: 

if (!has_undefined_max_size) {    total_max += u.max_size();  }

修复该问题的方式:增加代码处理没有定义init和max的情况  

if (has_undefined_init_size) {       total_init = (size_t)-1;    }  if (has_undefined_max_size) {        total_max = (size_t)-1;    }

 2、jmap不能获取数据原因

  jmap出现不能获取的原因:(UseAdaptiveSizePolicy + CMS同时使用会出现) (该状况源码: sun/jvm/hotspot/memory/GenerationFactory.java ):  

try {       return (Generation) ctor.instantiateWrapperFor(addr);  } catch (WrongTypeException e) {       return new Generation(addr) {       public String name() {       return "unknown generation type";  ……

 二、问题产生原因

    目前确认是jvm的bug,初步确认版本为1.6_u30以上,包括1.7都存在该问题.jdk6.30以下版本还未确认(使用1.6_u25版本后,目前还没有复现问题)---1.6.30以上到1.7的全部版本已经确认有该问题,jdk8修复,其他版本待验证

   简要原因分析请参见:        

   在使用cms算法下,如果开启参数UseAdaptiveSizePolicy,则每次minor gc后会重新计算eden,from和to的大小,计算过程依据的是gc过程统计的一些数据,计算后的eden+from+to不会超过Xmx,同时from和to一般是不相等(初始化的时候from和to是相等的)。主要问题在于计算完后,如果eden变大,ContiguousSpacePool里面的max_eden_size并没有被更新,还是最开始时候的值,这样导致jvm在通过call_special调用java.lang.management. MemoryUsage的构造函数的时候会产生exception,产生exception的原因是eden的committed 大于 eden的max_size,导致返回java.lang.management. MemoryUsage对象失败,最终导致产生显示异常。 

三、解决办法

  可以先设置 –XX:-UseAdaptiveSizePolicy来workaround,JDK的版本:sun jdk出问题后的版本目前看是只有jdk8修复;openjdk是hs25修复。 

转载地址:http://sopol.baihongyu.com/

你可能感兴趣的文章
【转】PHP中的Hash算法
查看>>
SqlLite的工具类SQLiteOpenHelper
查看>>
chgrp chown chmod
查看>>
nodejs中安装express
查看>>
2014软件表
查看>>
Struts2教程3:struts.xml常用配置解析
查看>>
(转帖)Implementing custom JavaFx Bindings
查看>>
mysql外键
查看>>
转发和重定向的区别
查看>>
<ecmall> ECMall的MySQL数据库调用
查看>>
SugarCRM - 如何修改默认首页
查看>>
Java日期类总结
查看>>
开关标识一个是0一个是-那个是开哪个是关
查看>>
ruby的并发和并行
查看>>
朱晶晶-六步制定好企业移动化战略
查看>>
SVPullToRefresh
查看>>
SSIndicatorLabel
查看>>
ASFBPostController
查看>>
Android实战技巧:Handler
查看>>
JqueryMobile实践点滴
查看>>