JVM 默认启动参数中,DisableExplicitGC 为 false,ExplicitGCInvokesConcurrent 为 false,对于大多数 GC (除了 ZGC 的其他 GC,包括 CMS,G1,Shenandoah GC 等等),都是会进行 FullGC 的,并且都是同步 GC 的,其中底层的原理会在另一篇详细分析,我们先来搞清楚为什么要留这样一个接口呢?

1. 使用并管理堆外内存的框架,需要 Full GC 的机制触发堆外内存回收

JVM 的内存,不止堆内存,还有其他很多块,通过 Native Memory Tracking 可以看到:

Native Memory Tracking:

Total: reserved=6308603KB, committed=4822083KB
- Java Heap (reserved=4194304KB, committed=4194304KB)
(mmap: reserved=4194304KB, committed=4194304KB) - Class (reserved=1161041KB, committed=126673KB)
(classes #21662)
( instance classes #20542, array classes #1120)
(malloc=3921KB #64030)
(mmap: reserved=1157120KB, committed=122752KB)
( Metadata: )
( reserved=108544KB, committed=107520KB)
( used=105411KB)
( free=2109KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=1048576KB, committed=15232KB)
( used=13918KB)
( free=1314KB)
( waste=0KB =0.00%) - Thread (reserved=355251KB, committed=86023KB)
(thread #673)
(stack: reserved=353372KB, committed=84144KB)
(malloc=1090KB #4039)
(arena=789KB #1344) - Code (reserved=252395KB, committed=69471KB)
(malloc=4707KB #17917)
(mmap: reserved=247688KB, committed=64764KB) - GC (reserved=199635KB, committed=199635KB)
(malloc=11079KB #29639)
(mmap: reserved=188556KB, committed=188556KB) - Compiler (reserved=2605KB, committed=2605KB)
(malloc=2474KB #2357)
(arena=131KB #5) - Internal (reserved=3643KB, committed=3643KB)
(malloc=3611KB #8683)
(mmap: reserved=32KB, committed=32KB) - Other (reserved=67891KB, committed=67891KB)
(malloc=67891KB #2859) - Symbol (reserved=26220KB, committed=26220KB)
(malloc=22664KB #292684)
(arena=3556KB #1) - Native Memory Tracking (reserved=7616KB, committed=7616KB)
(malloc=585KB #8238)
(tracking overhead=7031KB) - Arena Chunk (reserved=10911KB, committed=10911KB)
(malloc=10911KB) - Tracing (reserved=25937KB, committed=25937KB)
(malloc=25937KB #8666) - Logging (reserved=5KB, committed=5KB)
(malloc=5KB #196) - Arguments (reserved=18KB, committed=18KB)
(malloc=18KB #486) - Module (reserved=532KB, committed=532KB)
(malloc=532KB #3579) - Synchronizer (reserved=591KB, committed=591KB)
(malloc=591KB #4777) - Safepoint (reserved=8KB, committed=8KB)
(mmap: reserved=8KB, committed=8KB)
  • Java Heap: 堆内存,即-Xmx限制的最大堆大小的内存。
  • Class:加载的类与方法信息,其实就是 metaspace,包含两部分: 一是 metadata,被-XX:MaxMetaspaceSize限制最大大小,另外是 class space,被-XX:CompressedClassSpaceSize限制最大大小
  • Thread:线程与线程栈占用内存,每个线程栈占用大小受-Xss限制,但是总大小没有限制。
  • Code:JIT 即时编译后(C1 C2 编译器优化)的代码占用内存,受 -XX:ReservedCodeCacheSize限制
  • GC:垃圾回收占用内存,例如垃圾回收需要的 CardTable,标记数,区域划分记录,还有标记 GC Root 等等,都需要内存。这个不受限制,一般不会很大的。
  • Compiler:C1 C2 编译器本身的代码和标记占用的内存,这个不受限制,一般不会很大的
  • Internal:命令行解析,JVMTI 使用的内存,这个不受限制,一般不会很大的
  • Symbol: 常量池占用的大小,字符串常量池受-XX:StringTableSize 个数限制,总内存大小不受限制
  • Native Memory Tracking:内存采集本身占用的内存大小,如果没有打开采集(那就看不到这个了,哈哈),就不会占用,这个不受限制,一般不会很大的
  • Arena Chunk:所有通过 arena 方式分配的内存,这个不受限制,一般不会很大的
  • Tracing:所有采集占用的内存,如果开启了 JFR 则主要是 JFR 占用的内存。这个不受限制,一般不会很大的
  • Logging,Arguments,Module,Synchronizer,Safepoint,Other,这些一般我们不会关心。

除了 Native Memory Tracking 记录的内存使用,还有两种内存 Native Memory Tracking 没有记录,那就是:

  • Direct Buffer:直接内存
  • MMap Buffer:文件映射内存

针对除了堆内存以外,其他的内存,有些也是需要 GC 的。例如:MetaSpace,CodeCache,Direct Buffer,MMap Buffer 等等。早期在 Java 8 之前的 JVM,对于这些内存回收的机制并不完善,很多情况下都需要 FullGC 扫描整个堆才能确定这些区域中哪些内存可以回收。

有一些框架,大量使用并管理了这些堆外空间。例如 netty 使用了 Direct Buffer,Kafka 和 RocketMQ 使用了 Direct Buffer 和 MMap Buffer。他们都是提前从系统申请好一块内存,之后管理起来并使用。在空间不足时,继续向系统申请,并且也会有缩容。例如 netty,在使用的 Direct Buffer 达到-XX:MaxDirectMemorySize的限制之后,则会先尝试将不可达的Reference对象加入Reference链表中,依赖Reference的内部守护线程触发可以被回收DirectByteBuffer关联的Cleaner的run()方法。如果内存还是不足, 则执行System.gc(),期望触发full gc,来回收堆内存中的DirectByteBuffer对象来触发堆外内存回收,如果还是超过限制,则抛出java.lang.OutOfMemoryError.

2. 使用了 WeakReference, SoftReference 的程序,需要相应的 GC 回收。

对于 WeakReference,只要发生 GC,无论是 Young GC 还是 FullGC 就会被回收。SoftReference 只有在 FullGC 的时候才会被回收。当我们程序想主动对于这些引用进行回收的时候,需要能触发 GC 的方法,这就用到了System.gc()

3. 测试,学习 JVM 机制的时候

有些时候,我们为了测试,学习 JVM 的某些机制,需要让 JVM 做一次 GC 之后开始,这也会用到System.gc()

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

2021-2-26:为什么需要 System.gc() ?的更多相关文章

  1. Java的垃圾回收机制:强制回收System.gc() Runtime.getTime().gc()

    垃圾回收 当引用类型的实体,如对象.数组等不再被任何变量引用的时候.这块占用的内存就成为了垃圾.JVM会根据自己的策略决定是回收内存 注意: 垃圾回收只回收内存中的对象,无法回收物理资源(数据库连接, ...

  2. 实战Java虚拟机之四:提升性能,禁用System.gc() ?

    今天开始实战Java虚拟机之四:"禁用System.gc()". 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟 ...

  3. java: system.gc()和垃圾回收机制finalize

    System.gc()和垃圾回收机制前的收尾方法:finalize(收尾机制) 程序退出时,为每个对象调用一次finalize方法,垃圾回收前的收尾方法 System.gc() 垃圾回收方法 clas ...

  4. System.gc()与Object.finalize()的区别

    finalize()是由JVM自动调用的,你可以用System.gc(),但JVM不一定会立刻执行,JVM感觉内存空间有限时,才会开始执行finalize(),至于新的对象创建个数和被收集个数不同是因 ...

  5. finalize与System.gc()

    finalize Finalize是Object类的一个方法,可以用来被重写 finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只 ...

  6. System.gc

    Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进”内存回收的机制的,其中最显眼的就是这个System.gc()函数. 乍一看这个函数似乎是可以进行垃圾回收的 ...

  7. 由dubbo服务禁用system.gc而引起的思考

    我一直都有一个疑问,丰巢业务服务的生产环境jvm参数设置是禁止system.gc的,也就是开启设置:-XX:+DisableExplicitGC,但是生产环境却从来没有出现过堆外内存溢出的情况.说明一 ...

  8. (转)调用System.gc没有立即执行的解决方法

    调用System.gc没有立即执行的解决方法 查看源码 当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收,查看系统源码可以看到 /** * Indicate ...

  9. void java.lang.System.gc()

    void java.lang.System.gc() Runs the garbage collector. Calling the gc method suggests that the Java ...

  10. System.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放

    首先我们修改下JVM的启动参数,重新运行之前博客中的代码.JVM启动参数和测试代码如下: -verbose:gc -XX:+PrintGCDetails -XX:+DisableExplicitGC ...

随机推荐

  1. linux 一分钟搭建zookeeper linux 单机版(亲测可用)

    wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gzt ...

  2. linux虚拟摄像头vivid配置

    总述    最近在看摄像头驱动,需要配置虚拟摄像头的驱动,但是教程里面是linux2.6内核的,实际电脑的是Ubuntu16,内核是linux4.15版本,从2.6到4.15内核好多文件发生了变化,所 ...

  3. Codeforces Round #651 (Div. 2) C. Number Game (博弈,数学)

    题意:对于正整数\(n\),每次可以选择使它变为\(n-1\)或者\(n/t\) (\(n\ mod\ t=0\)且\(t\)为奇数),当\(n=1\)时便不可以再取,问先手赢还是后手赢. 题解:首先 ...

  4. 国产网络损伤仪SandStorm -- 基本概念:什么是仿真引擎

    "仿真引擎"在网络损伤仪SandStorm(www.minismb.com)或者网络IP仿真损伤仪中是一个最基本概念,它就相当于一个由两个物理以太网口组成的"网桥&quo ...

  5. k8s-0-集群

    Docker回顾 docker容器封装应用程序好处 内核在3.8以上,才能完整使用docker隔离功能(所有centos6不推荐用) Docker容器化封装应用程序缺点 容器编排工具有哪些 一: K8 ...

  6. spring再学习之AOP准备

    一.aop思想: 横向重复,纵向抽取 1.乱码 2.事务管理 3,action 二.spring能够为容器中管理的对象生成代理对象 1.spring能帮我们生成代理对象 2.spring实现aop的原 ...

  7. Qt开发Activex笔记(一):环境搭建、基础开发流程和演示Demo

    前言   使用C#开发动画,绘图性能跟不上,更换方案使用Qt开发Qt的控件制作成OCX以供C#调用,而activex则是ocx的更高级形式.  QtCreator是没有Active控件项目的,所有需要 ...

  8. linux无需root挂载iso镜像文件

    引言 起初,我在针对deepin制作一款appimage安装工具,想要其实现的功能就是自动获取图标,只需要输入软件名称和分类即可,当然以后也会寻找方案省去手动输入的麻烦. 后来我发现一个有趣的问题 o ...

  9. KEIL + STM32 续

    接上一篇,debug出现问题 1.手动安装STM32 芯片包   Keil.STM32F1xx_DFP.2.2.0.pack; https://www.keil.com/dd2/Pack/ 百度网盘  ...

  10. Lightoj 1038 - Race to 1 Again【期望+dp】

    题目:戳这里 题意:一个数字n不断迭代地除以自身的因子得到1.求这个过程中操作除法次数的期望. 解题思路: 求概率基本都是从一个最基础的状态开始延伸推出公式,得出答案.因为每个数都有个共同的最终状态1 ...