CMS 垃圾收集器

2020-03-08 05:18:38 +08:00
 linwu

CMS 垃圾收集器垃圾收集大概分为 4 个阶段:

( 1 )初始标记
( 2 )并发标记预清除
( 3 )重新标记
( 4 )并发清除

在 ( 2 )并发标记预清除阶段,因为还有用户线程在进行,可能会有对象引用的更改, 所以需要( 3 )重新标记 重新修正存活对象

那么在( 4 )并发清除阶段(也是有用户线程在进行), 清除的时候,如果用户线程更改了对象的引用,导致原先一个应该不算存活的对象存活了 那么清除又将该对象清除了怎么办?

网上看了很多答案,没有说的很清楚,都是扯到了浮动垃圾上,浮动垃圾应该算是新产生的对象吧,也不会被清除,就是因为不被清除,才可能导致新的 GC

也看了《深入理解 Java 虚拟机》也没有一个很好的解释。

希望理解的朋友可以解答下

3848 次点击
所在节点    Java
20 条回复
btnokami
2020-03-08 05:29:05 +08:00
想象力有限,楼主能举个已经丢失引用的对象被再次引用的例子吗
linwu
2020-03-08 05:57:52 +08:00
public static void main(String[] args) {
A a = new A();
a.b = new B();

C c = new C();
c.b = a.b;

a = null;
}

class A {

...
}

class A {
...
}

class A {
...
}
linwu
2020-03-08 06:00:27 +08:00
class A {
B b;
...
}

class C {
B b;
...
}

class B {
...
}
linwu
2020-03-08 06:06:05 +08:00
好像不行哈哈,那书上说的"标记期间应用可能被正在运行并更新引用"是什么意思呢?弄不懂
btnokami
2020-03-08 07:20:24 +08:00
@linwu 这个更新引用并不是指失去引用的对象被重新引用吧,而是指在运行期间这个对象有了新的引用,这样在做 tri-color marking 的时候颜色可能会被修改。
yafoo
2020-03-08 07:46:23 +08:00
以为你专门收集整理过时的 cms 系统呢
sagaxu
2020-03-08 09:40:48 +08:00
几年前 cms 就被废弃了,怎么还有人考古?
Jacky23333
2020-03-08 10:34:47 +08:00
@sagaxu 面试要问
bbao
2020-03-08 10:40:59 +08:00
@sagaxu 现在普遍 G1 了?
liuming
2020-03-08 11:22:27 +08:00
"标记期间应用可能被正在运行并更新引用"指的是在初始标记时还存活但到重新标记时成垃圾了的情况吧
sagaxu
2020-03-08 11:51:25 +08:00
@bbao 2015 年提出废弃 cms,2017 年 Java 9 默认 g1,cms 则被标记为废弃。2019 年提出要删除 cms 相关代码,下下周将要发布的 Java 14 不再包含 cms 相关代码,从此用不了 cms。

@Jacky23333 有些面试还喜欢问 Java 7 和 Java 8 的 map 实现有什么不同。这种喜欢考古和面试专用 100 问的面试,反而简单,不用动脑,背宝典可破。
bbao
2020-03-08 14:25:24 +08:00
@sagaxu 仁兄,现在还是否用 java,生产环境 JVM 配置的垃圾收集是什么?
rrfeng
2020-03-08 14:53:54 +08:00
CMS 有一个 stw ( stop the world )阶段,意思是啥都不干只进行垃圾收集的。
sagaxu
2020-03-08 15:09:28 +08:00
@bbao 生产环境 g1,gc 只设置了两个参数,Xmx 和 MaxGCPauseMillis。
Jacky23333
2020-03-08 15:17:26 +08:00
如果一个对象被判定为死亡,也就是不可达的,那你还能通过什么办法去更改到这个对象的引用,也就是说 a = new Instance();a = null,那你还能够怎样去访问到 Instance()并更改它的引用呢。所以应该不会出现你所说的问题
bbao
2020-03-08 15:17:40 +08:00
@rrfeng 第一次初始标记和重新标记都是 STW,标记对象,并不进行垃圾收集。在预清理阶段会有 minor gc 的发生,减少重新标记时对象的数量和减少 stw 时间。
zrc
2020-03-08 15:23:08 +08:00
这些线程都是到了 safepoint 的时候才 stw 吧,可能和 safepoint 的定义点有关
gaius
2020-03-08 15:57:55 +08:00
再次标记是扫并发标记改变阶段改变的对象,我的理解是对象地址,如果不修正一下会因为地址错误清理不了,应该不会出现垃圾又被重新引用的情况吧?
optional
2020-03-08 16:08:05 +08:00
因为是并发标记,有些引用在 register 和 cpu cache 里吧
Goooogle
2020-03-08 17:10:49 +08:00
如何判断一个对象是否还在被引用?
JVM 会从栈帧、常量区、方法区、Native 区中的引用开始进行可达性分析,当一个对象不可达后,才能会标记为可回收,放入 finalize 队列,去执行 finalize 方法。当执行完 finalize 方法后(或许不会执行),如该对象还是不可达,那这个对象就真的无法再被代码访问到。(毕竟 Java 不能直接操作指针)

到于浮动垃圾,是指在进行可达性分析时,新生成了对象,或者是原有的可达对象在经过一段时间后引用引用状态变成不可达。


所以根本问题在于:当对象标记为不可达后,真的就不会再回来了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/650831

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX