JVM 源码解读之 CMS GC 触发条件

jvm原理之SystemGC源码分析 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可以通过jmap来触发等,针对每个场景其实我们都可以写篇文章来做一个介绍,本文重点介绍下System.gc的原理 或许大家已经知道如下相关的知识 system.gc其实是做一次full gc system.gc会暂停整个进程 system.gc一般情况下我们要禁掉,使用-XX:+DisableExplicitGC system.gc在cms gc下我 阅读详情

前言
经常有同学会问,为啥我的应用 Old Gen 的使用占比没达到 CMSInitiatingOccupancyFraction 参数配置的阈值,就触发了 CMS GC,表示很莫名奇妙,不知道问题出在哪?

其实 CMS GC 的触发条件非常多,不只是 CMSInitiatingOccupancyFraction 阈值触发这么简单。本文通过源码全面梳理了触发 CMS GC 的条件,尽可能的帮你了解平时遇到的奇奇怪怪的 CMS GC 问题。

先抛出一些问题,来吸引你的注意力。

为什么 Old Gen 使用占比仅 50% 就进行了一次 CMS GC? Metaspace 的使用也会触发 CMS GC 吗? 为什么 Old Gen 使用占比非常小就进行了一次 CMS GC?

触发条件
CMS GC 在实现上分成 foreground collector 和 background collector。foreground collector 相对比较简单,background collector 比较复杂,情况比较多。

下面我们从 foreground collector 和 background collector 分别来说明他们的触发条件:

说明:本文内容是基于 JDK 8 说明:本文仅涉及 CMS GC 的触发条件,至于算法的具体过程,以及什么时候进行 MSC(mark sweep compact)不在本文范围

foreground collector
foreground collector 触发条件比较简单,一般是遇到对象分配但空间不够,就会直接触发 GC,来立即进行空间回收。采用的算法是 mark sweep,不压缩。

background collector
说明 background collector 的触发条件之前,先来说下 background collector 的流程,它是通过 CMS 后台线程不断的去扫描,过程中主要是判断是否符合 background collector 的触发条件,一旦有符合的情况,就会进行一次 background 的 collect。

void ConcurrentMarkSweepThread::run() {    
  ...//省略    
  while (!_should_terminate) {    
    sleepBeforeNextCycle();    
    if (_should_terminate) break;    
    GCCause::Cause cause = _collector->_full_gc_requested ?    
      _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;    
    _collector->collect_in_background(false, cause);    
  }    
  ...//省略    
}
每次扫描过程中,先等 CMSWaitDuration 时间,然后再去进行一次 shouldConcurrentCollect 判断,看是否满足 CMS background collector 的触发条件。CMSWaitDuration 默认时间是 2s(经常会有业务遇到频繁的 CMS GC,注意看每次 CMS GC 之间的时间间隔,如果是 2s,那基本就可以断定是 CMS 的 background collector)。

void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {    
  while (!_should_terminate) {    
    if (CMSIncrementalMode) {    
      icms_wait();    
      if(CMSWaitDuration >= 0) {    
        // Wait until the next synchronous GC, a concurrent full gc    
        // request or a timeout, whichever is earlier.    
        wait_on_cms_lock_for_scavenge(CMSWaitDuration);    
      }    
      return;    
    } else {    
      if(CMSWaitDuration >= 0) {    
        // Wait until the next synchronous GC, a concurrent full gc    
        // request or a timeout, whichever is earlier.    
        wait_on_cms_lock_for_scavenge(CMSWaitDuration);    
      } else {    
        // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently    
        wait_on_cms_lock(CMSCheckInterval);    
      }    
    }    
    // Check if we should start a CMS collection cycle    
    if (_collector->shouldConcurrentCollect()) {    
      return;    
    }    
    // .. collection criterion not yet met, let's go back    
    // and wait some more    
  }    
}
那 shouldConcurrentCollect() 方法中都有哪些条件呢?

bool CMSCollector::shouldConcurrentCollect() {    
  // 第一种触发情况    
  if (_full_gc_requested) {    
    if (Verbose && PrintGCDetails) {    
      gclog_or_tty->print_cr("CMSCollector: collect because of explicit "    
                             " gc request (or gc_locker)");    
    }    
    return true;    
  }    
  // For debugging purposes, change the type of collection.    
  // If the rotation is not on the concurrent collection    
  // type, don't start a concurrent collection.    
  NOT_PRODUCT(    
    if (RotateCMSCollectionTypes &&    
        (_cmsGen->debug_collection_type() !=    
          ConcurrentMarkSweepGeneration::Concurrent_collection_type)) {    
      assert(_cmsGen->debug_collection_type() !=    
        ConcurrentMarkSweepGeneration::Unknown_collection_type,    
        "Bad cms collection type");    
      return false;    
    }    
  )    
  FreelistLocker x(this);    
  // ------------------------------------------------------------------    
  // Print out lots of information which affects the initiation of    
  // a collection.    
  if (PrintCMSInitiationStatistics && stats().valid()) {    
    gclog_or_tty->print("CMSCollector shouldConcurrentCollect: ");    
    gclog_or_tty->stamp();    
    gclog_or_tty->print_cr("");    
    stats().print_on(gclog_or_tty);    
    gclog_or_tty->print_cr("time_until_cms_gen_full %3.7f",    
      stats().time_until_cms_gen_full());    
    gclog_or_tty->print_cr("free="SIZE_FORMAT, _cmsGen->free());    
    gclog_or_tty->print_cr("contiguous_available="SIZE_FORMAT,    
                           _cmsGen->contiguous_available());    
    gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate());    
    gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate());    
    gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy());    
    gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy());    
    gclog_or_tty->print_cr("metadata initialized %d",    
      MetaspaceGC::should_concurrent_collect());    
  }    
  // ------------------------------------------------------------------    
  // 第二种触发情况    
  // If the estimated time to complete a cms collection (cms_duration())    
  // is less than the estimated time remaining until the cms generation    
  // is full, start a collection.    
  if (!UseCMSInitiatingOccupancyOnly) {    
    if (stats().valid()) {    
      if (stats().time_until_cms_start() == 0.0) {    
        return true;    
      }    
    } else {    
      // We want to conservatively collect somewhat early in order    
      // to try and "bootstrap" our CMS/promotion statistics;    
      // this branch will not fire after the first successful CMS    
      // collection because the stats should then be valid.    
      if (_cmsGen->occupancy() >= _bootstrap_occupancy) {    
        if (Verbose && PrintGCDetails) {    
          gclog_or_tty->print_cr(    
            " CMSCollector: collect for bootstrapping statistics:"    
            " occupancy = %f, boot occupancy = %f", _cmsGen->occupancy(),    
            _bootstrap_occupancy);    
        }    
        return true;    
      }    
    }    
  }    
  // 第三种触发情况    
  // Otherwise, we start a collection cycle if    
  // old gen want a collection cycle started. Each may use    
  // an appropriate criterion for making this decision.    
  // XXX We need to make sure that the gen expansion    
  // criterion dovetails well with this. XXX NEED TO FIX THIS    
  if (_cmsGen->should_concurrent_collect()) {    
    if (Verbose && PrintGCDetails) {    
      gclog_or_tty->print_cr("CMS old gen initiated");    
    }    
    return true;    
  }    
  // 第四种触发情况    
  // We start a collection if we believe an incremental collection may fail;    
  // this is not likely to be productive in practice because it's probably too    
  // late anyway.    
  GenCollectedHeap* gch = GenCollectedHeap::heap();    
  assert(gch->collector_policy()->is_two_generation_policy(),    
         "You may want to check the correctness of the following");    
  if (gch->incremental_collection_will_fail(true /* consult_young */)) {    
    if (Verbose && PrintGCDetails) {    
      gclog_or_tty->print("CMSCollector: collect because incremental collection will fail ");    
    }    
    return true;    
  }    
  // 第五种触发情况    
  if (MetaspaceGC::should_concurrent_collect()) {    
      if (Verbose && PrintGCDetails) {    
      gclog_or_tty->print("CMSCollector: collect for metadata allocation ");    
      }    
      return true;    
    }    
  return false;    
}
上述代码可知,从大类上分, background collector 一共有 5 种触发情况:

1.是否是并行 Full GC

指的是在 GC cause 是 gclocker 且配置了 GCLockerInvokesConcurrent 参数, 或者 GC cause 是javalangsystemgc(就是 System.gc()调用)and 且配置了 ExplicitGCInvokesConcurrent 参数,这时会触发一次 background collector。

2.根据统计数据动态计算(仅未配置 UseCMSInitiatingOccupancyOnly 时) 未配置 UseCMSInitiatingOccupancyOnly 时,会根据统计数据动态判断是否需要进行一次 CMS GC。

判断逻辑是,如果预测 CMS GC 完成所需要的时间大于预计的老年代将要填满的时间,则进行 GC。 这些判断是需要基于历史的 CMS GC 统计指标,然而,第一次 CMS GC 时,统计数据还没有形成,是无效的,这时会跟据 Old Gen 的使用占比来判断是否要进行 GC。

if (!UseCMSInitiatingOccupancyOnly) {    
    if (stats().valid()) {    
      if (stats().time_until_cms_start() == 0.0) {    
        return true;    
      }    
    } else {    
      // We want to conservatively collect somewhat early in order    
      // to try and "bootstrap" our CMS/promotion statistics;    
      // this branch will not fire after the first successful CMS    
      // collection because the stats should then be valid.    
      if (_cmsGen->occupancy() >= _bootstrap_occupancy) {    
        if (Verbose && PrintGCDetails) {    
          gclog_or_tty->print_cr(    
            " CMSCollector: collect for bootstrapping statistics:"    
            " occupancy = %f, boot occupancy = %f", _cmsGen->occupancy(),    
            _bootstrap_occupancy);    
        }    
        return true;    
      }    
    }    
  }
那占多少比率,开始回收呢?(也就是 bootstrapoccupancy 的值是多少呢?) 答案是 50%。或许你已经遇到过类似案例,在没有配置 UseCMSInitiatingOccupancyOnly 时,发现老年代占比到 50% 就进行了一次 CMS GC,当时的你或许还一头雾水呢。

 _bootstrap_occupancy = ((double)CMSBootstrapOccupancy)/(double)100;    
 //参数默认值    
 product(uintx, CMSBootstrapOccupancy, 50,    
          "Percentage CMS generation occupancy at which to initiate CMS collection for bootstrapping collection stats")  
3.根据 Old Gen 情况判断

bool ConcurrentMarkSweepGeneration::should_concurrent_collect() const {    
  assert_lock_strong(freelistLock());    
  if (occupancy() > initiating_occupancy()) {    
    if (PrintGCDetails && Verbose) {    
      gclog_or_tty->print(" %s: collect because of occupancy %f / %f  ",    
        short_name(), occupancy(), initiating_occupancy());    
    }    
    return true;    
  }    
  if (UseCMSInitiatingOccupancyOnly) {    
    return false;    
  }    
  if (expansion_cause() == CMSExpansionCause::_satisfy_allocation) {    
    if (PrintGCDetails && Verbose) {    
      gclog_or_tty->print(" %s: collect because expanded for allocation ",    
        short_name());    
    }    
    return true;    
  }    
  if (_cmsSpace->should_concurrent_collect()) {    
    if (PrintGCDetails && Verbose) {    
      gclog_or_tty->print(" %s: collect because cmsSpace says so ",    
        short_name());    
    }    
    return true;    
  }    
  return false;    
}
从源码上看,这里主要分成两类: (a) Old Gen 空间使用占比情况与阈值比较,如果大于阈值则进行 CMS GC 也就是"occupancy() > initiatingoccupancy()",occupancy 毫无疑问是 Old Gen 当前空间的使用占比,而 initiatingoccupancy 是多少呢?

 _cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio);    
 ...    
 void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, uintx tr) {    
  assert(io <= 100 && tr <= 100, "Check the arguments");    
  if (io >= 0) {    
    _initiating_occupancy = (double)io / 100.0;    
  } else {    
    _initiating_occupancy = ((100 - MinHeapFreeRatio) +    
                             (double)(tr * MinHeapFreeRatio) / 100.0)    
                            / 100.0;    
  }    
}
可以看到当 CMSInitiatingOccupancyFraction 参数配置值大于 0,就是 “io / 100.0”;

当 CMSInitiatingOccupancyFraction 参数配置值小于 0 时(注意,默认是 -1),是 “((100 - MinHeapFreeRatio) + (double)(tr * MinHeapFreeRatio) / 100.0) / 100.0”,这到底是多少呢?是 92%,这里就不贴出具体的计算过程了,或许你已经在某些书或者博客中了解过,CMSInitiatingOccupancyFraction 没有配置,就是 92,但是其实 CMSInitiatingOccupancyFraction 没有配置是 -1,所以阈值取后者 92%,并不是 CMSInitiatingOccupancyFraction 的值是 92。

(b) 接下来没有配置 UseCMSInitiatingOccupancyOnly 的情况

这里也分成有两小类情况:

当 Old Gen 刚因为对象分配空间而进行扩容,且成功分配空间,这时会考虑进行一次 CMS GC;

根据 CMS Gen 空闲链判断,这里有点复杂,目前也没整清楚,好在按照默认配置其实这里返回的是 false,所以默认是不用考虑这种触发条件了。

4.根据增量 GC 是否可能会失败(悲观策略)

什么意思呢?两代的 GC 体系中,主要指的是 Young GC 是否会失败。如果 Young GC 已经失败或者可能会失败,JVM 就认为需要进行一次 CMS GC。

  bool incremental_collection_will_fail(bool consult_young) {    
    // Assumes a 2-generation system; the first disjunct remembers if an    
    // incremental collection failed, even when we thought (second disjunct)    
    // that it would not.    
    assert(heap()->collector_policy()->is_two_generation_policy(),    
           "the following definition may not be suitable for an n(>2)-generation system");    
    return incremental_collection_failed() ||    
           (consult_young && !get_gen(0)->collection_attempt_is_safe());    
  }
我们看两个判断条件,“incrementalcollectionfailed()” 和 “!getgen(0)->collectionattemptissafe()” incrementalcollectionfailed() 这里指的是 Young GC 已经失败,至于为什么会失败一般是因为 Old Gen 没有足够的空间来容纳晋升的对象。

!getgen(0)->collectionattemptissafe() 指的是新生代晋升是否安全。 通过判断当前 Old Gen 剩余的空间大小是否足够容纳 Young GC 晋升的对象大小。 Young GC 到底要晋升多少是无法提前知道的,因此,这里通过统计平均每次 Young GC 晋升的大小和当前 Young GC 可能晋升的最大大小来进行比较。

//av_promo 是平均每次 YoungGC 晋升的大小,max_promotion_in_bytes 是当前可能的最大晋升大小( eden+from 当前使用空间的大小)    
bool   res = (available >= av_promo) || (available >= max_promotion_in_bytes);
5.根据 meta space 情况判断

这里主要看 metaspace 的 shouldconcurrent_collect 标志,这个标志在 meta space 进行扩容前如果配置了 CMSClassUnloadingEnabled 参数时,会进行设置。这种情况下就会进行一次 CMS GC。因此经常会有应用启动不久,Old Gen 空间占比还很小的情况下,进行了一次 CMS GC,让你很莫名其妙,其实就是这个原因导致的。

总结
本文梳理了 CMS GC 的 foreground collector 和 background collector 的触发条件,foreground collector 的触发条件相对来说比较简单,而 background collector 的触发条件比较多,分成 5 大种情况,各大种情况种还有一些小的触发分支。尤其是在没有配置 UseCMSInitiatingOccupancyOnly 参数的情况下,会多出很多种触发可能,一般在生产环境是强烈建议配置 UseCMSInitiatingOccupancyOnly 参数,以便于能够比较确定的执行 CMS GC,另外,也方便排查 GC 原因。
————————————————
版权声明:本文为优快云博主「涤生的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_45410925/article/details/96424540

C#开发者必备:VSPD虚拟串口快速配置指南(附汉化教程) 本文为C#开发者提供了VSPD虚拟串口的快速配置与汉化教程。详细介绍了如何安装、汉化VSPD,并创建稳定的虚拟串口对,重点讲解了如何将其集成到C#开发工作流中,使用SerialPort类进行数据通信测试、协议模拟及故障排查,有效提升硬件通信开发的效率。 阅读详情

相关推荐

三菱FX5U通信之CCLINK操作步骤

11. 连接 CC‐Link 用的端子排,连接 Ver.1.10 对应 CC‐Link 专用电缆。备注:1、以上对应的寄存器都是一一对应的,主站的点数可以比从站多,但是都需要一一对应起来。3.直接安装孔,用于直接安装的螺钉孔(2‐φ4.5,安装螺钉为 M4 螺钉)2.点阵 LED(显示模块中设置的站号和测试模式的内容)5.次段扩展连接器(连接扩展模块的扩展电缆的连接器)4.动作状态(显示 LED 显示模块的动作状态)10 电源连接器,用于连接电源电缆的连接器。1.扩展电缆(扩展时连接用的电缆)

ZXL622722的博客 6926

JVM触发Full GC的条件

Java虚拟机主流的垃圾收集器:cms、G1 。未来的趋势是基于大内存回收的ZGC,ZGC也是Jdk11版本的默认垃圾收集器。 以jdk1.8为例,讲讲触发Full GC的条件: 图中展示了7种不同分代的收集器:Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1; 新生代收集器:Serial、ParNew、Para...

Dark不必 3469

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube

本教程基于群晖的NAS设备DS423+的docker功能进行搭建,DSM版为 7.2.1-69057 Update 5。MetaTube是一个媒体服务器插件,主要用于Emby和Jellyfin媒体服务器。它的主要功能是从互联网上抓取内容并响应 JSON 数据,然后通过预安装的 MetaTube 插件请求服务器并下载相应的元数据,以与 Jellyfin/Emby 服务器配合使用。使用 MetaTube 的步骤大致如下:部署后端:首先,需要部署一个名为​ 的后端 API 服务器来抓取内容。

小小笔记大大用处 1万+

JVM 详解之 CMS收集器

1.CMS触发GC的条件 CMS GC 在实现上分成 foreground collector 和 background collector。foreground collector 相对比较简单,background collector 比较复杂,情况比较多。 foreground collector foreground collector 触发条件比较简单,一般是如下: 老年代没有足够的连续空间分配给晋升的对象(即使总可用内存足够大)。 新生代没有足够的空间分配对象。 老年代没有足够的剩余空间来容纳

吉他程序员的博客 2856

单细胞分析进阶:sctransform标准化在Seurat中的实战解析

本文深入解析了sctransform标准化方法在Seurat单细胞分析中的实战应用。通过对比传统对数标准化,sctransform能更有效地建模并剔除技术噪音,提升数据质量。文章提供了从环境配置、数据准备、核心参数解析到完整流程整合的详细指南,并针对常见问题给出解决方案,帮助研究者获得更清晰的细胞分群和更可靠的差异表达结果。

weixin_29248313的博客 150

解决2020R2,2022R1等版本的SCDM无法编辑草图尺寸的问题

解决2020R2,2022R1等版本的SCDM无法编辑草图尺寸的问题

y_u_yu_yu_的博客 1万+

JVM中的垃圾收集器 -- CMS

垃圾收集器 新生代收集器 1.Serial收集器 概念:Serial收集器是一个单线程的收集器,它在进行垃圾收集的时候,必须暂停其他所有的工作线程,直到它搜集结束。(Stop the world) 优点:简单而高效(与其它单线存放收集器相比) 应用:运行在Client模式下的虚拟机的默认新生代收集器。 说明:在桌面应用中,分配给虚拟机管理的内存一般不会很大,收集几十兆或者几百兆的新生代,停顿的时间还不到一秒,只要不是频繁发生,这点停顿还是可以接受的 2.Parallel Scavenge.

java小兵 3260

【深度学习基础】多任务学习(Multi-Task Learning)

多任务学习(Multi-task learning)是和单任务学习(single-task learning)相对的一种机器学习方法。在机器学习领域,标准的算法理论是一次学习一个任务,也就是系统的输出为实数的情况。复杂的学习问题先被分解成理论上独立的子问题,然后分别对每个子问题进行学习,最后通过对子问题学习结果的组合建立复杂问题的数学模型。多任务学习是一种联合学习,多个任务并行学习,结果相互影响。一次只学习一个任务(task),大部分的机器学习任务都属于单任务学习。

十二月的猫 1万+

【大厂面试题系列】:说说Young GC(Minor GC) 和 Full GC的触发条件【JVM】

文章目录1. 调用 System.gc()2. 老年代空间不足3. 空间分配担保失败4. JDK 1.7 及以前的永久代空间不足5. CMS GC时出现Concurrent Mode Failure 1. 调用 System.gc() 只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。 2. 老年代空间不足 老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。 为了避免以上原因引起的 Full GC,应当尽量.

Code皮皮虾的博客 2035

YOLOv8源码解析与复现:ShuffleAttention:高效的混合注意力机制 实现通道和空间混合注意力

随着深度学习在计算机视觉领域的飞速发展,卷积神经网络(CNNs)已经成为图像分类、目标检测、语义分割等任务的核心。为了进一步提升模型的性能,研究者们引入了“注意力机制”,旨在让网络能够动态地关注输入数据中最具信息量的部分。经典的注意力模块,如SE-Net(Squeeze-and-Excitation Networks)和CBAM(Convolutional Block Attention Module),通过通道注意力或结合通道与空间注意力,显著增强了模型的特征表达能力。

FJN110的博客 554

Spring AI 实战:如何使用 MCP Server 搭建 MCP 天气查询服务

MCP(Model Context Protocol)是 Anthropic 提出的一种开放协议,它定义了AI 模型与外部世界交互的标准方式。通俗地说:大模型本身只拥有训练数据中的知识,它不知道今天的天气、无法查询你的数据库、不能调用你的内部 API。MCP 就是解决这个问题的"桥梁"——它让模型能够发现并使用外部工具(Tools),就像人用手去操作工具一样。角色职责对应依赖MCP Server暴露工具(Tool),供模型调用MCP Client连接 Server,让模型发现和使用工具本文我们先聚焦。

SmartSi 756

JVM 源码解读之 CMS 何时会进行 Full GC

t点击上方"涤生的博客",关注我转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注。前言本文内容是基于 JDK 8在文章 JVM 源码解读之 CMS GC ...

阿杜的世界 1487

干掉百度Apollo的安装!(Apollo10.0的源码安装)

1、在Apollo10.0的安装手册中,没有再详细给出源码安装的步骤,官方更推荐的是包管理安装,但实际上Apollo10.0仍然是可以进行源码安装的。2、使用源码安装Apollo10.0,比Apollo9.0的源码安装问题要少,整个安装过程更顺畅。3、从Apollo 10.0开始,源码安装和包管理安装采用同一套编译工具,也就是aem。之前只有在进行包管理安装的时候我们才需要安装aem,现在进行源码安装也需要安装aem。

qq_40033030的博客 892

CMS几种GC模式解读

在G1出来之前,CMS绝对是OLTP系统的标配。即使G1出来几年了,生产环境很多的JVM实例还是采用ParNew+CMS的组合。但是即使其得到这么广泛的应用,还是有很多同学对它有很深的误解。本文主要对ParNew+CMS经典组合下,触发的几种垃圾回收方式进行几个概念的纠正。 Backgroud CMS 可能更多人只知道CMS,而不知道Backgroud CMS。事实上我们说的CMS,即包含了5个阶...

阿飞Javaer的专栏 2377

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

初步诊断你的GC

前言 JVM的GC机制让Java程序员省去了自己垃圾回收的烦恼,大大提高了生产效率。但是正因为JVM垃圾回收机制足够优秀,导致很多Java程序员对JVM这个黑盒了解甚少,很多人没有去了解它,很多人也没机会去了解它。然而要想成为一名优秀的Java程序员,了解JVM和它的GC机制,写出JVM GC机制更喜欢的代码,是必须要掌握的一门技术; 这篇文章我主要说一下如何初步诊断JVM的GC是否正常,重点...

赵树祥的博客 4170

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

触发Full GC的时机

由于Full GC的耗时是Minor GC的十倍左右,所以Full GC的频率设计得比Minor GC低得多。现总结一下触发Full GC的情况。 在那些实现了CMS的比较新的虚拟机中,如果配置了-XX:+UseConcMarkSwapGC,则启用CMS回收算法,CMS会周期性地检查老年代的情况,每隔一定时间(默认2秒),就检查是否需要对老年代进行一次CMS回收,判断的依据如下: ...

a55684471的博客 1015

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

gc就是fullgc吗 major_你的JVM还好吗?GC初步诊断

来源:公众号阿飞Javaer , 作者 阿飞的博客JVM的GC机制绝对是很多程序员的福音,它让Java程序员省去了自己回收垃圾的烦恼。从而可以把大部分时间专注业务身上,大大提高了业务开发速度,让产品需求尽快的落地抢占市场。但是也正因为如此,导致很多Java程序员对JVM和GC知之甚少,以我愚见大家对JVM&GC不够了解的有几个原因:门槛太高。我们平常接触的spring,dubbo,java...

weixin_39645268的博客 434

01-JVM 内存模型与 GC 原理

本文从 JVM 的内存模型出发,详细解析了堆结构、GC 算法与主流收集器,结合日志调优与源码进行系统讲解,并融入了面试视角与实战经验。掌握 JVM 原理是 Java 工程师高阶进阶的必经之路。📌 后续预告:下一篇将深入分析 Java 类加载机制及其破坏与替代方案,敬请期待。

無言的博客 1107

JVM - CMS深度剖析

文章目录PreCMSJVM参数阶段 Pre JVM-04垃圾收集Garbage Collection(上)【垃圾对象的判定】 JVM-05垃圾收集Garbage Collection(中)【垃圾收集算法】 JVM-06垃圾收集Garbage Collection(下)【垃圾收集器】 JVM - 再聊GC垃圾收集算法及垃圾收集器 CMS Concurrent Mark Sweep 并发标记清除 。 CMS 收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用,它是

小工匠 2万+
上一篇: 理解CMS GC日志
下一篇: Jackson /常用注解/ annotation
achuo
博客等级 码龄18年 491粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值