JVM:gc什么时候开始?System.gc()能保证gc一定发生吗?
gc什么时候开始?
“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?”
在什么时候:
1.新生代有一个Eden区和两个survivor区,首先将对象放入Eden区,如果空间不足就向其中的一个survivor区上放,如果仍然放不下就会引发一次发生在新生代的minor GC,将存活的对象放入另一个survivor区中,然后清空Eden和之前的那个survivor区的内存。在某次GC过程中,如果发现仍然又放不下的对象,就将这些对象放入老年代内存里去。
2.大对象以及长期存活的对象直接进入老年区。
3.当每次执行minor GC的时候应该对要晋升到老年代的对象进行分析,如果这些马上要到老年区的老年对象的大小超过了老年区的剩余大小,那么执行一次Full GC以尽可能地获得老年区的空间。
对什么东西:从GC Roots搜索不到,而且经过一次标记清理之后仍没有复活的对象。
做什么:
新生代:复制清理;
老年代:标记-清除和标记-压缩算法;
永久代:存放Java中的类和加载类的类加载器本身。
GC Roots都有哪些:
1. 虚拟机栈中的引用的对象
2. 方法区中静态属性引用的对象,常量引用的对象
3. 本地方法栈中JNI(即一般说的Native方法)引用的对象。
友情链接:Java GC的那些事(上)
友情链接:Java GC的那些事(下)
友情链接:CMS垃圾收集器介绍
垃圾回收算法有哪些?
答:
引用计数 :原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为 0 的对象。此算法最致命的是无法处理循环引用的问题;
标记-清除 :此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除;
此算法需要暂停整个应用,同时,会产生内存碎片;
复制算法 :此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中;
此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现 “碎片” 问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间;(8:1:1需要内存担保)
标记-整理 :此算法结合了 “标记-清除” 和 “复制” 两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象 “压缩” 到堆的其中一块,按顺序排放。
此算法避免了 “标记-清除” 的碎片问题,同时也避免了 “复制” 算法的空间问题。
类似-Xms、-Xmn 这些参数的含义:
答:
堆内存分配:
JVM 初始分配的内存由-Xms 指定,默认是物理内存的 1/64;
JVM 最大分配的内存由-Xmx 指定,默认是物理内存的 1/4;
默认空余堆内存小于 40% 时,JVM 就会增大堆直到-Xmx 的最大限制;空余堆内存大于 70% 时,JVM 会减少堆直到 -Xms 的最小限制;
因此服务器一般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
非堆内存分配:
JVM 使用-XX:PermSize 设置非堆内存初始值,默认是物理内存的 1/64;
由 XX:MaxPermSize 设置最大非堆内存的大小,默认是物理内存的 1/4;
-Xmn2G:设置年轻代大小为 2G;
-XX:SurvivorRatio,设置年轻代中 Eden 区与 Survivor 区的比值。
System.gc()能保证gc一定发生吗?
查看源码
当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收,查看系统源码可以看到
/**
* Indicates to the VM that it would be a good time to run the
* garbage collector. Note that this is a hint only. There is no guarantee
* that the garbage collector will actually be run.
*/
public static void gc() {
boolean shouldRunGC;
synchronized(lock) {
shouldRunGC = justRanFinalization;
if (shouldRunGC) {
justRanFinalization = false;
} else {
runGC = true;
}
}
if (shouldRunGC) {
Runtime.getRuntime().gc();
}
}
也就是justRanFinalization=true的时候才会执行
查找发现当调用runFinalization()的时候justRanFinalization变为true
下面是runFinalization()的源码
/**
* Provides a hint to the VM that it would be useful to attempt
* to perform any outstanding object finalization.
*/
public static void runFinalization() {
boolean shouldRunGC;
synchronized(lock) {
shouldRunGC = runGC;
runGC = false;
}
if (shouldRunGC) {
Runtime.getRuntime().gc();
}
Runtime.getRuntime().runFinalization();
synchronized(lock) {
justRanFinalization = true;
}
}
1234567891011121314151617181920
其实当我们直接调用System.gc()只会把这次gc请求记录下来,等到runFinalization=true的时候才会先去执行GC,runFinalization=true之后会在允许一次system.gc()。之后在call System.gc()还会重复上面的行为。
所以System.gc()要跟System.runFinalization()一起搭配使用才好。
查看ZygoteInit.java 里面 gc()和runFinalizationSync()是配合使用的,这样才有效果
static void gcAndFinalize() {
final VMRuntime runtime = VMRuntime.getRuntime();
/* runFinalizationSync() lets finalizers be called in Zygote,
* which doesn't have a HeapWorker thread.
*/
System.gc();
runtime.runFinalizationSync();
System.gc();
}12345678910
解决方案
由此可见,当我们需要调用的System.gc()的时候 要这样才会执行
System.gc();
runtime.runFinalizationSync();
System.gc();123
其实这个gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的对策。
不过个人建议不到万不得已不要调用,因为jvm有自己的gc策略,根本不需要我们来手动
JVM:gc什么时候开始?System.gc()能保证gc一定发生吗?相关推荐
- jvm中的年轻代 老年代 持久代 gc ----------转载
jvm中的年轻代 老年代 持久代 gc 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation) ...
- java每隔一小时fullgc_JVM菜鸟进阶高手之路六(JVM每隔一小时执行一次Full GC)
以为上次问题是rmi的问题就此结束了,但是问题并没有结束,其实本次问题不是rmi问题导致的,但是rmi也的确可能会有sys.gc fullgc问题. 查看GC统计汇总情况: jstat -gcutil ...
- JVM面试(四)-垃圾回收、垃圾收集器、GC日志
垃圾回收.垃圾收集器.GC日志 什么是垃圾?(垃圾的概念) 什么是垃圾回收?(垃圾回收的概念) 为什么要垃圾回收?(垃圾回收的原因) 如何定义垃圾? 引用计数算法 什么是循环引用 可达性分析算法 哪些 ...
- java 年轻代算法_java内存模型 年轻代/年老代 持久区,jvm中的年轻代 老年代 持久代 gc...
虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...
- JVM 菜鸟进阶高手之路六(JVM每隔一小时执行一次Full GC)
上次分析详细地址在:http://blog.csdn.net/lirenzuo/article/details/76257526 以为上次问题是rmi的问题就此结束了,但是问题并没有结束,其实本次问题 ...
- jQuery 一次定时器_为什么JVM每隔一小时执行一次Full GC?
随着接口自动化监控的完善,线上大多数的接口都被自动化监控系统接入,因此开发.测试人员可以及时的了解API的健康情况,监控内容包括检查API的状态码是否正常.返回的内容断言是否成功等,异常的接口会对外发 ...
- jvm中的年轻代 老年代 持久代 gc
虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...
- 【JVM进阶之路】垃圾回收机制和GC算法之三色标记(三)
JVM往期文章 [JVM进阶之路]内存结构(一) [JVM进阶之路]玩转JVM中的对象(二) 上篇文章中讲到JVM中的对象以及判断对象的存活,那么对于"已死"的对象应该如何处理,怎 ...
- 精华推荐 | 【JVM深层系列】「GC底层调优系列」一文带你彻底加强夯实底层原理之GC垃圾回收技术的分析指南(GC原理透析)
前提介绍 很多小伙伴,都跟我反馈,说自己总是对JVM这一块的学习和认识不够扎实也不够成熟,因为JVM的一些特性以及运作机制总是混淆以及不确定,导致面试和工作实战中出现了很多的纰漏和短板,解决广大小伙伴 ...
最新文章
- elixir官方入门教程 模式匹配
- Tensorflow:Tensorboard使用
- 关于汇编跟C/C++已经java的内存理解
- HR 的那些黑话大全,太扎心了!(漫画)
- python做带数据库的登录界面_Python3 Tkinkter + SQLite实现登录和注册界面
- OpenShift 4 - 对镜像进行合规扫描,加固应用镜像安全
- 社群数据分析:你运营的社群是好社群吗?
- 对自注意力(self-attention)的理解以及基于pytorch的简易示例
- 牛客网暑期ACM多校训练营(第五场): A. gpa(01分数规划)
- dotNET中创建自定义的配置节
- 安装mysql-server之后,root用户不能登录问题
- Dynamips GNS3
- abb变频器580系列改中文,ACS580变频器参数设置.pdf
- Android Studio中ListView通过自定义Adapter显示数据3-1
- 2021牛客多校#10 F-Train Wreck(数学,优先队列)
- 汇川plc支持c语言吗,汇川PLC可编程控制器的功能特点
- win7计算机属性资源管理器停止工作,Win7系统Windows资源管理器已停止工作怎么解决?...
- 数字用计算机写大写,微信小程序学习用:大写计算器;数字转换为大写
- linux怎么滑动命令行窗口_如何在Linux命令行界面愉快进行性能测试
- C语言用if语句判断规定字符串