当前位置: 首页 > news >正文

温州网站建设咨询药品网络营销公司

温州网站建设咨询,药品网络营销公司,日照网站开发,装修设计网站哪家好写在前面: 版本信息: jdk版本:jdk8u40 垃圾回收器:ParallelScavenge new/old最近在群里看到有一位老哥拿着异常信息到处问,而发生的就是java.lang.OutOfMemoryError: GC overhead limit exceeded异常,恰好…

写在前面:

版本信息:

jdk版本:jdk8u40
垃圾回收器:ParallelScavenge new/old

最近在群里看到有一位老哥拿着异常信息到处问,而发生的就是java.lang.OutOfMemoryError: GC overhead limit exceeded异常,恰好看到经常有人询问关于这个异常的问题,如何发生的,要如何解决呢?所以促使我写下这篇文章,此文章分为3大块,出现的原因,如何解决,源码论证。

异常出现的原因

full gc回收时间大于98%(这里是一个算法,可以忽略,只需要明白最近一直花大量时间在GC),并且回收后可用空间小于总空间的2%。 这样的情况下,达到5次就会抛出java.lang.OutOfMemoryError: GC overhead limit exceeded异常。

总而言之:我们首先要明白,GC的过程是需要STW(STOP-THE-WORD) 也即业务线程是需要停止工作,而GC过程中消耗大量时间回收空间,而回收后的可使用空间仅仅只有总空间的2%,往往下次new对象的时候又去GC了,周而复始,给用户的体验是当前系统已经完全卡死了~

所以在种种因素下JVM认为你已经没必要去GC了,GC也是毫无意义的事情了,完全卡死的情况下,还不如我给你抛出java.lang.OutOfMemoryError: GC overhead limit exceeded异常,开发者好好去排查一下问题~

如何解决

仅供参考,还是需要分析自身系统环境做出不同的策略。

  1. 堆空间是否设置的太少?可以在启动时添加-Xms -Xmx参数设置堆大小
  2. 分析是否存在内存泄露?
  3. 如果项目庞大,是否需要提升硬件?
  4. 启动时添加-XX:+HeapDump0n0ut0fMemoryError   -XX:HeapDumpPath= "路径" 参数下次发生OOM时便可分析
  5. 分析项目中经常使用的大对象,是否可以优化一下空间?
  6. 是否可以把项目中非重要的缓存数据设置成软、弱引用对象
  7. 以上的分析可以使用阿里开源的 "Arthas" 工具
  8. 还有很多笔者暂时没有考虑到的.......

源码论证

由于大部分的公司还是停留在Java8,并且垃圾回收器也是默认的ParallelScavenge new/old,所以直接给出ParallelScavenge new/old垃圾回收器的部分核心源码

src/share/vm/gc_interface/collectedHeap.inline.cpp 文件中, common_mem_allocate_noinit方法,此方法尝试开辟对象,如果开辟不成功,就会根据当前不同OOM异常种类Dump和抛出对应的异常

HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) {bool gc_overhead_limit_was_exceeded = false;// 尝试在堆空间开辟对象result = Universe::heap()->mem_allocate(size,&gc_overhead_limit_was_exceeded);// 根据gc_overhead_limit_was_exceeded参数区分是那种OOM异常。if (!gc_overhead_limit_was_exceeded) {// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support// 英文注释特别明显了,如果设置了dump参数,就导出report_java_out_of_memory("Java heap space");// 抛出OOM:Java heap spaceTHROW_OOP_0(Universe::out_of_memory_error_java_heap());} else {      // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support// 英文注释特别明显了,如果设置了dump参数,就导出report_java_out_of_memory("GC overhead limit exceeded");// 抛出OOM:GC overhead limit exceededTHROW_OOP_0(Universe::out_of_memory_error_gc_overhead_limit());}
}

而我们关心的是GC overhead limit exceeded异常,而这里是根据gc_overhead_limit_was_exceeded变量来做区分,而gc_overhead_limit_was_exceeded变量传入mem_allocate方法,所以我们接着看mem_allocate方法src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp 文件中mem_allocate方法,此方法也是开辟对象的过程。

HeapWord* ParallelScavengeHeap::mem_allocate(size_t size,bool* gc_overhead_limit_was_exceeded) {// 尝试在young_gen空间创建对象HeapWord* result = young_gen()->allocate(size);// 在年轻代没有创建出对象。while (result == NULL) {{// 因为存在锁的原因,所以下面又在年轻代尝试了一次。MutexLocker ml(Heap_lock);gc_count = Universe::heap()->total_collections();result = young_gen()->allocate(size);if (result != NULL) {return result;}// 年轻代开辟不了,老年代尝试一下。result = mem_allocate_old_gen(size);if (result != NULL) {return result;}// 超过允许尝试的次数,直接返回if (gclocker_stalled_count > GCLockerRetryAllocationCount) {return NULL;}}// 需要触发GC,回收空间后再尝试开辟对象if (result == NULL) {// 触发GC回收空间VM_ParallelGCFailedAllocation op(size, gc_count);VMThread::execute(&op);if (op.prologue_succeeded()) {// 是否达到次数,是否清空软引用了const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();const bool softrefs_clear = collector_policy()->all_soft_refs_clear();if (limit_exceeded && softrefs_clear) {// 设置为true,代表抛出GC overhead limit exceeded异常*gc_overhead_limit_was_exceeded = true;   size_policy()->set_gc_overhead_limit_exceeded(false);return NULL;}return op.result();}}}return result;
}

我们看到后续GC回收后,判断limit_exceeded 和 softrefs_clear,如果都为true就把gc_overhead_limit_was_exceeded设置为true。

而softrefs_clear变量是清空软引用,我们知道,在JVM中,内存实在不足的时候会清空软引用

而我们看到limit_exceeded变量的设置即可。看何时把他设置为true即可。

src/share/vm/gc_implementation/share/adaptiveSizePolicy.cpp 文件中check_gc_overhead_limit方法

void AdaptiveSizePolicy::check_gc_overhead_limit(size_t young_live,size_t eden_live,size_t max_old_gen_size,size_t max_eden_size,bool   is_full_gc,GCCause::Cause gc_cause,CollectorPolicy* collector_policy) {// 当前eden空闲大小const size_t free_in_eden = max_eden_size > live_in_eden ?max_eden_size - live_in_eden : 0;// 当前老年代空闲大小const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());// 当前堆空间空闲大小const size_t total_free_limit = free_in_old_gen + free_in_eden;// 堆空间的总大小const size_t total_mem = max_old_gen_size + max_eden_size;// GCHeapFreeLimit是2// 所以这里是算出比例,2%const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0);const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0);// GCTimeLimit是98// 所以这里是算出比例,98%const double gc_cost_limit = GCTimeLimit/100.0;// 如果是fullgcif (is_full_gc) {// 如果GC时长超过98%// 并且回收后可用空间小于总空间的2%if (gc_cost() > gc_cost_limit &&free_in_old_gen < (size_t) mem_free_old_limit &&free_in_eden < (size_t) mem_free_eden_limit) {inc_gc_overhead_limit_count();    // 自增一次// 如果开启了次数限制if (UseGCOverheadLimit) {// 如果次数大于等于5次。if (gc_overhead_limit_count() >=AdaptiveSizePolicyGCTimeLimitThreshold){// 设置为true,到时候就会抛出GC overhead limit exceeded异常// 并且清空次数set_gc_overhead_limit_exceeded(true);   reset_gc_overhead_limit_count();} }}}// 如果设置了UseGCOverheadLimit的情况下, 不会响应此异常if (UseGCOverheadLimit && PrintGCDetails && Verbose) {if (gc_overhead_limit_exceeded()) {reset_gc_overhead_limit_count();} }
}

这里算出了堆总空间的百分之2,gc回收时间的百分之98。然后算出了GC后空闲空间的占比,GC的回收时间。最后通过比较,如果GC回收时间大于98%,并且回收后可用空间小于总空间的2% 情况下计数器+1,如果计数器达到5次就通过set_gc_overhead_limit_exceeded方法设置为true,最终抛出java.lang.OutOfMemoryError: GC overhead limit exceeded异常。

所以看了源码后,解决GC overhead limit exceeded异常,还可以通过设置

-XX:-UseGCOverheadLimit 或者 -XX:AdaptiveSizePolicyGCTimeLimitThreshold = "设置很大的数值" 都能让JVM不抛出 GC overhead limit exceeded异常。但是没任何意义,因为会一直触发GC,一直STW暂停,用户一直是卡死的状态~

http://www.15wanjia.com/news/29278.html

相关文章:

  • 创新的南昌网站建设百度推广登录地址
  • 手机网站qq登录插件bt种子bt天堂
  • 昆明网站建设天锐科技云客网平台
  • 多个链接的网站怎么做的网络市场的四大特点
  • 网站建设代理开发科技企业服务整合网络营销外包
  • 6黄页网站建设微信搜一搜排名优化
  • 网站毕业设计代做百度seo学院
  • 北京网站建设手机app电脑软件推广平台
  • 邯郸网站设计怎么申请百度精简版网页入口
  • 国内一家做国外酒店团购的网站自己想开个网站怎么弄
  • 哪个网站可以做笔译兼职珠海seo快速排名
  • 摄影网站怎么做数据库定制企业网站建设制作
  • 做电子元器件的网站知乎关键词排名工具
  • 广安网站建设谷歌网页版
  • 太仓网站开发qq群引流推广软件
  • 贵阳网站建设-中国互联网络营销岗位招聘信息
  • 常熟住房和城乡建设局网站百度账户代运营
  • 有什么比较好的做海报网站百度推广深圳分公司
  • wordpress 折叠菜单厦门关键词排名优化
  • 永兴县网站建设公司百度搜图片功能
  • 做视频网站需要什么服务器站长平台
  • 净化工程 技术支持 东莞网站建设如何建立网站
  • 建站网站abc什么是竞价推广
  • 南县人民政府门户网站大学生网页制作成品模板
  • 电子商务网站网站建设北京网站推广
  • 网站建设与网页设计制作书籍网页制作代码模板
  • 可以做英语阅读理解的网站上海seo服务
  • 网做英文网站东莞推广
  • wordpress软件模板下载西安seo教程
  • 莱西网站制作联赛与超搭建网站的软件