2021-2-26:为什么需要 System.gc() ?
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() ?的更多相关文章
- Java的垃圾回收机制:强制回收System.gc() Runtime.getTime().gc()
垃圾回收 当引用类型的实体,如对象.数组等不再被任何变量引用的时候.这块占用的内存就成为了垃圾.JVM会根据自己的策略决定是回收内存 注意: 垃圾回收只回收内存中的对象,无法回收物理资源(数据库连接, ...
- 实战Java虚拟机之四:提升性能,禁用System.gc() ?
今天开始实战Java虚拟机之四:"禁用System.gc()". 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟 ...
- java: system.gc()和垃圾回收机制finalize
System.gc()和垃圾回收机制前的收尾方法:finalize(收尾机制) 程序退出时,为每个对象调用一次finalize方法,垃圾回收前的收尾方法 System.gc() 垃圾回收方法 clas ...
- System.gc()与Object.finalize()的区别
finalize()是由JVM自动调用的,你可以用System.gc(),但JVM不一定会立刻执行,JVM感觉内存空间有限时,才会开始执行finalize(),至于新的对象创建个数和被收集个数不同是因 ...
- finalize与System.gc()
finalize Finalize是Object类的一个方法,可以用来被重写 finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只 ...
- System.gc
Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进”内存回收的机制的,其中最显眼的就是这个System.gc()函数. 乍一看这个函数似乎是可以进行垃圾回收的 ...
- 由dubbo服务禁用system.gc而引起的思考
我一直都有一个疑问,丰巢业务服务的生产环境jvm参数设置是禁止system.gc的,也就是开启设置:-XX:+DisableExplicitGC,但是生产环境却从来没有出现过堆外内存溢出的情况.说明一 ...
- (转)调用System.gc没有立即执行的解决方法
调用System.gc没有立即执行的解决方法 查看源码 当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收,查看系统源码可以看到 /** * Indicate ...
- void java.lang.System.gc()
void java.lang.System.gc() Runs the garbage collector. Calling the gc method suggests that the Java ...
- System.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放
首先我们修改下JVM的启动参数,重新运行之前博客中的代码.JVM启动参数和测试代码如下: -verbose:gc -XX:+PrintGCDetails -XX:+DisableExplicitGC ...
随机推荐
- Java并发包源码学习系列:阻塞队列实现之LinkedBlockingDeque源码解析
目录 LinkedBlockingDeque概述 类图结构及重要字段 linkFirst linkLast unlinkFirst unlinkLast unlink 总结 参考阅读 系列传送门: J ...
- Flink-v1.12官方网站翻译-P004-Flink Operations Playground
Flink操作训练场 在各种环境中部署和操作Apache Flink的方法有很多.无论这种多样性如何,Flink集群的基本构件保持不变,类似的操作原则也适用. 在这个操场上,你将学习如何管理和运行Fl ...
- JDK中jps、jinfo、jstat、jstack、jmap、jconsole等命令简介
JDK提供了几个很实用的工具,如下: jinfo:观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数,java class path等信息.命令格式:jinf ...
- Codeforces Round #649 (Div. 2) A. XXXXX
题目链接:https://codeforces.com/contest/1364/problem/A 题意 找出大小为 $n$ 的数组 $a$ 的最长连续子数组,其元素和不被 $x$ 整除. 题解 如 ...
- AtCoder Beginner Contest 162
比赛链接:https://atcoder.jp/contests/abc162/tasks A - Lucky 7 #include <bits/stdc++.h> using names ...
- Codeforces Round #660 (Div. 2) A. Captain Flint and Crew Recruitment、Captain Flint and a Long Voyage
题目链接:Captain Flint and Crew Recruitment 题意: t组输入,每一组输入一个n.这里我们说一下题目定义的近似质数概念: "如果可以将正整数x表示为p⋅q, ...
- rabbitmq常见面试题
1.使用RabbitMQ有什么好处?1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦! 2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方 ...
- python程序配置守护进程
参考博客 python Supervisor 使用与配置_a35155的博客-CSDN博客 Ubuntu系统下:apt-get install supervisor,通过这种方式安装后,自动设置为开机 ...
- 如何创建一个GETH节点(单节点,windows环境)
所有命令都是在powershell上执行的 1.创建"创世块" 初始化配置 创建一个 hdgenesis.json文件,拷贝到geth根目录 { "config&q ...
- python 调用麦克风;摄像头;截屏;
# -*- coding: utf-8 -*- """ Created on Mon Jun 24 14:47:35 2019 @author: erio "& ...
