java GC 循序渐进100 问 - 1. 基础与概念

前言

果然懒是写博客最大的阻碍.

通过向别人清楚地解说一件事,来确认自己真的弄懂了这件事。[费曼学习法]

①②③等用来表示 参考的文献/网址

目标

GC 入门

1. java 中的 GC 是什么

java 是一门可以自动管理内存的语言, 它运行在 jvm 之上, 所以根本上来说是 jvm 可以自动管理内存, jvm 通过gc (垃圾回收)来进行内存控制.

2. 对象在什么时候可以被回收

不再使用的对象②. 一般一个对象不再被引用(可能有循环引用问题->1.3),就代表该对象可以被回收

  1. 语法垃圾(程序可能无法到达的那些对象)
  2. 语义垃圾(程序实际上将不再使用的那些对象)

3. 如何判断对象是否可被回收?

一般判断一个对象是否可以被回收有两种方法

  1. 引用计数法
  2. 可达性分析算法

3.1 引用计数法是什么? 有什么缺点?

很难解决循环引用的问题

3.2 简述可达性分析算法

可达性分析算法通过一组 GC ROOTS (一组活跃的引用①) 作为起点 , 从这些节点向下搜索, 标记所有与之关联的对象 . 标记完成之后, 没有被标记的对象就称之为 不可用对象(垃圾回收的目标)

可达性分析算法可以解决 循环引用的问题

3.3 不安全的可达性分析, 如误报/漏报, 会造成哪些问题?

在多线程环境下,其他线程可能会更新已经访问过的对象中的引用 ④

  • 误报, 损失一部分垃圾回收的对象
  • 漏报, 即忘记标记了, 在标记时, 有其他线程new了新的对象, 最后回收时, jvm认为这个对象没有被标记, 于是回收了这个实际存活的对象

3.4 如何"安全"地进行可达性分析?

  1. 找到所有 GC ROOTS
  2. 标记时 Stop the world, 停止其他非垃圾回收线程的工作

3.5 如何找到所有的 GC Roots (3.2 延伸)

GC roots 这组引用是tracing GC ①②的起点。要实现语义正确的tracing GC,就必须要能完整枚举出所有的GC roots,否则就可能会漏扫描应该存活的对象,导致GC错误回收了这些被漏扫的活对象.

在java语言中, GC roots 这组引用可能包括 ①③

  • 所有Java线程当前活跃的栈帧里指向GC堆里的对象的引用;换句话说,当前所有正在被调用的方法的引用类型的参数/局部变量/临时值。
  • VM中静态数据结构里指向GC堆里的对象的引用,例如说HotSpot VM里的Universe里有很多这样的引用。
  • JNI handles,包括global handles和local handles
  • (看情况)所有当前被加载的Java类
  • (看情况)Java类的引用类型静态变量
  • (看情况)Java类的运行时常量池里的引用类型常量(String或Class类型)
  • (看情况)String常量池(StringTable)里的引用

4. STOP THE WORLD (STW)

4.1 STW 是什么?

停止其他非垃圾回收线程的工作 (停止用户线程工作)

4.2 为什么 GC 需要 stw ?

根本原因在于: jvm 需要移动对象并更新引用, 但当应用程序线程仍在运行时,很难安全地实现这一目标。

hotspot 目前提供的所有垃圾回收器都会 stw, 不管是Part GC 还是 FULL GC

4.3 如何进行 STOP THE WORLD ?

  • Java 虚拟机中的 Stop-the-world 是通过安全点(safepoint)机制来实现的
  • jvm 收到 stw 请求后, 它会等待所有线程到达 safepoint, 才允许 stw 的线程独占工作
  • 安全点的初始目的并不是让其他线程停下,而是找到一个稳定的执行状态。在这个执行状态下,Java 虚拟机的堆栈不会发生变化。这么一来,垃圾回收器便能够“安全”地执行可达性分析。④

4.3.2 Stop The World的四个阶段 ⑥

使用 -XX:+PrintSafepointStatistics 来输出 gc stw 的情况

         vmop                    [threads: total initially_running wait_to_block]    [time: spin block sync cleanup vmop] page_trap_count
1.027: no vm operation                [      19          1              2    ]      [  1093     0  1093     0     0    ]  0   
  • Spin阶段。因为jvm在决定进入全局safepoint的时候,有的线程在安全点上,而有的线程不在安全点上,这个阶段是等待未在安全点上的用户线程进入安全点。
  • Block阶段。即使进入safepoint,用户线程这时候仍然是running状态,保证用户不在继续执行,需要将用户线程阻塞。⑦这篇bog详细说明了如何将用户线程阻塞。
    • sync 等于 spin+block,这是从开始到进入安全点所耗的时间,可用于判断进入安全点耗时
  • Cleanup。这个阶段是JVM做的一些内部的清理工作。
  • VM Operation. JVM执行的一些全局性工作,例如GC,代码反优化。

4.4 有哪些地方可以设置安全点检测?

我们可以在代码中加入安全点检测, 当 stw 请求发出后, 检查是否需要暂停执行

  1. 解释执行的字节码之间
  2. JNI API 调用 Java 方法, 访问对象时
  3. 阻塞的线程由于处于 Java 虚拟机线程调度器的掌控之下,因此属于安全点。
  4. JIT 生成机器码时, 即时编译器需要插入安全点检测
    • HotSpot 虚拟机的做法便是在生成代码的方法出口以及非计数循环的循环回边(back-edge)处插入安全点检测。

4.5 长时间没有进入安全点对GC的影响 ?

-Xmx50M -Xms50M -XX:+PrintGCDateStamps -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics

    public static void foo() {
        long l1 = System.currentTimeMillis();
        for (int i = 0; i < 0x77777777; i++) {
            sum += Math.sqrt(i);
        }
        long l2 = System.currentTimeMillis();
        System.out.println(String.format("foo: %dms", l2 - l1));
    }

2019-10-12T23:32:23.767+0800: Total time for which application threads were stopped: 1.0933449 seconds, Stopping threads took: 1.0931842 seconds

原因是有线程迟迟进入不到safepoint来阻塞,导致其他已经停止的线程也一直等待,VM Thread也在等待所有的Java线程都进入到safepoint阻塞才能开始GC。

参考

转载请注明出处

作者: GiraffeTree - https://giraffetree.me/2019/10/13/java_gc_100_quesions_1/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容