• godtrue 置顶
    2018-08-16
    非常感谢,此篇可用通俗易懂来形容,其他同学问的问题也很棒!

    小结:

    1:垃圾回收-核心工作就是回收垃圾,哪关键点回来了。什么是垃圾?这个垃圾需要分类嘛?怎么定位垃圾?怎么回收垃圾?回收垃圾的方法都有哪些?他们都有什么优缺点?另外,就是我们为什么要学习垃圾回收?

    2:站在JVM的视角来看
    垃圾-就是无用对象所占用的堆内存空间
    貌似不需要垃圾分类,识别垃圾并回收就行
    定位垃圾,是垃圾回收的关键点

    晚安💤,明天继续写
    展开
    
     9
  • 旭东 置顶
    2018-08-28
    赞,这种循序渐进的讲法,不知道了怎么工作,还知道了为啥要设计成这样,Why和what都和谐的在一起讲了
    
     1
  • 茶底
    2018-08-15
    老师下一期能讲一下g1算法吗。讲深一点😁
    
     25
  • godtrue
    2018-08-17
    非常感谢,此篇可用通俗易懂来形容,其他同学问的问题也很棒!

    小结:

    1:垃圾回收-核心工作就是回收垃圾,哪关键点回来了。什么是垃圾?这个垃圾需要分类嘛?怎么定位垃圾?怎么回收垃圾?回收垃圾的方法都有哪些?他们都有什么优缺点?另外,就是我们为什么要学习垃圾回收?

    2:站在JVM的视角来看

    垃圾-就是无用对象所占用的堆内存空间

    垃圾分类-貌似不需要垃圾分类,识别垃圾并回收就行

    定位垃圾-是垃圾回收的关键点,无用的对象占用的堆空间即是垃圾,那就需要先定位无用的对象,这里的无用是不再使用的意思,咋判断呢?文中介绍了两种方法,计数法和标记法(祥看原文)核心在于能定位出无用的对象,后出现的方法往往比早出现的更好一点,这里也一样,标记法能解决计数法,解决不了的循环引用不能回收的问题,但是也存在其他的问题,误报和漏报的问题,误报浪费点垃圾回收的机会浪费点空间,漏报在多线程并发工作时可能会死JVM的,所以,比较严重,所以,JVM采用了简单粗暴的stop-the-world的方式来对待,所以,老年代的回收有卡顿的现象

    怎么回收垃圾-定位出垃圾,回收就是一个简单的事情了,当然也非常关键,把要回收的堆内存空间标记为可继续使用就行,下次有新对象能在此空间创建就行

    回收垃圾的方法-文中介绍了三种,清除、压缩、复制

    清除法-简单,但易产生碎片,可能总空间够但分配不了的问题
    压缩法-能解决清除法的问题,但是复杂且耗性能
    复制法-折衷一些,但是空间利用率低,总之,各有千秋

    为什么要学-这个最容易,因为面试需要、装逼需要、升职加薪需要、人类天生好奇、还有免于被鄙视及可以鄙视其他人
    展开

    作者回复: 赞!

     2
     20
  • Geek_488a8e
    2018-08-31
    误报和漏报,我觉得可惜这样理解,垃圾回收是先标记活的对象,后回收死的对象,那么如果标记好后,其它线程产生了垃圾,即将活的变死了,这种内存是不会释放的。另外,如果这时产生了新对象,由于没被标记为活的,所以被释放了,这就危险了
    
     12
  • godtrue
    2018-08-17
    疑问❓
    1:JVM的stop-the-world机制非常不友好,有哪些解决之道?原理是什么?
    2:压测时出现频繁的gc容易理解,但是有时出现毛刺是因为什么呢?
    3:fullgc有卡顿,对性能很不利,怎么避免呢?

    作者回复: 1. 采用并行GC可以减少需要STW的时间。它们会在即时编译器生成的代码中加入写屏障或者读屏障。

    2. Y轴应该是时间,那毛刺就是长暂停。一般Full GC就会造成长暂停。

    3. 通过调整新生代大小,使对象在其生命周期内都待在新生代中。这样一来,Minor GC时就可以收集完这些短命对象了。

     2
     11
  • suynan
    2019-03-06
    安全点的这个地方,看得我是一脸懵逼
    
     10
  • Leon Wong
    2018-09-11
    老师你好,例子里的foo方法中的for循环,其中i变量类型我从int型改成long型后,长暂停的现象不存在了,请问是为何?

    作者回复: 这是C2一个诡异的地方。

    for (int i=start; i<limit; i++) {..}

    对于int类型的循环变量i,如果满足 1) 基于该循环变量的循环出口只有一个,即i < limit,2) 循环变量随着迭代的增量为常数,例子中i++即增量为1,以及循环变量的上限(当增量为负数时则是下限)为循环无关的,即limit应是循环无关,那么C2会将其判断成计数循环(counted loop),然后默认不插入safepoint。

    而对于long类型的循环变量,C2直接识别为非计数循环,需要插入safepoint。

    
     8
  • 彩色的沙漠
    2018-08-15
    @正是那朵玫瑰老师有几个不明白的地方,误报和漏报不太明白:
    1、假设A引用开始指向A1对象:A------>A1,按老师说的误报就是将引用A指向null:A------>null,那么此时A1对象不是没有引用了,不就可以垃圾回收了么,为什么会错过垃圾回收的机会呢?
    2、漏报,是将A引用指向一个未被访问的对象假设对象为B:A----->B,此时A引用原来指向的对象应该没有引用了吧,为什么会垃圾回收器可能会回收事实上仍被引用的对象呢?

    2018-08-15

     作者回复

    这里指的是,GC已经标记完成,然后其他线程进行修改的情况(也是并发GC所要解决的问题)。

    当GC标记完成,还未开始回收时,你更新了其中一个引用,使之指向null,那么原来指向的对象本可以被回收的。

    如果指向一个新的对象,这个对象可没有被标记为不能回收,垃圾回收器就直接给回收掉了

    老师我也有和@正是那朵玫瑰一样的问题,看了老师的讲解,还是不太明白。GC标记完成,那GC标记的是引用还是具体的堆空间对象。如果标记的具体的堆空间对象,并不会造成GC并发问题,误报和漏报,改变的是引用关系。请老师解答,谢谢!
    展开
    
     5
  • same old love
    2019-06-17
    我有个疑问,就是JVM回收掉对象以后,存活下来对象的内存地址值会不会改变
     1
     4
  • Jussi Lee
    2018-09-29
    一、垃圾回收算法
          1、引用计数法(文中已经介绍,主要的缺点是无法处理循环引用;在每次引用的产生和消除的时候,会伴随着一个加法或者减法的操作,对性能有一定的影响)
          2、标记清除法(从根节点出发开始所有可达的对象,未被标记的就是垃圾对象。主要缺点是产生空间碎片)
          3、复制算法(将原空间分为两块,每次使用其中一块,在垃圾回收时,进行复制,然后转换使用的内存空间。主要的缺点是将系统的内存折半。主要适用于存活对象少,垃圾对象多的情况下)
          4、标记压缩法(从根出发对所有可达对象进行一次标记,然后进行压缩。最后进行清理)
          5、分代算法(每一种垃圾回收算法都有其优缺点。分代算法是根据对象的特点分成几块,新建的对象放入新生代区域,当一个对象经历了几次复制后还存活则放入老年代。老年代因为对象存活率高复制算法不适用,因此采取标记清除或者标记压缩)
          6、分区算法(把堆空间划分为连续的不同小区间。降低了GC产生的影响)
    展开
    
     4
  •  素丶  
    2019-08-09
    结合 Rx 的回答容易帮助理解。
    https://www.zhihu.com/question/53613423/answer/135743258
    
     3
  • 正是那朵玫瑰
    2018-08-15
    老师有几个不明白的地方,误报和漏报不太明白:
    1、假设A引用开始指向A1对象:A------>A1,按老师说的误报就是将引用A指向null:A------>null,那么此时A1对象不是没有引用了,不就可以垃圾回收了么,为什么会错过垃圾回收的机会呢?
    2、漏报,是将A引用指向一个未被访问的对象假设对象为B:A----->B,此时A引用原来指向的对象应该没有引用了吧,为什么会垃圾回收器可能会回收事实上仍被引用的对象呢?

    作者回复: 这里指的是,GC已经标记完成,然后其他线程进行修改的情况(也是并发GC所要解决的问题)。

    当GC标记完成,还未开始回收时,你更新了其中一个引用,使之指向null,那么原来指向的对象本可以被回收的。

    如果指向一个新的对象,这个对象可没有被标记为不能回收,垃圾回收器就直接给回收掉了

    
     3
  • 茶底
    2018-08-15
    老师下一期能讲一下g1算法吗。讲深一点😁
    
     3
  • jiaobuchongจุ๊บ
    2019-02-17
    1、文中所说的误报和漏报是不是说反了啊,
         并发环境下标记完后,线程将引用改成 null,导致损失了部分垃圾回收的机会,这是属于漏报吧?
         已标记,然后将引用设置为未被访问过的对象,导致回收了仍被引用的内存,这个属于误报吧?
    2、在标记的过程中,是不是只需要记录存活的对象就行,不用标记垃圾对象,后续在执行回收算法的时候,也只是在操作已经标记的存活的对象?
    
     2
  • javaadu
    2018-12-13
    @茶底,这是我写的G1学习笔记:https://www.jianshu.com/p/a3e6a9de7a5d
    
     2
  • WolvesLeader
    2018-08-17
    很是不明白,我的理解有没有stop the word 是和垃圾回收器有关的,看完之后怎么觉得您的意思是,不管什么垃圾回收器都会出现stop the word

    作者回复: 目前的垃圾回收器多多少少需要stop the world,但都在朝着尽量减少STW时间发展。

    完全的并发GC算法是存在的,但是在实现上一般都会在枚举GC roots时进行STW。

    
     2
  • no13bus
    2018-08-15
    昨天看书正好看到这章节,真的不错
    
     2
  • life is short, e...
    2018-10-16
    老师,我心中有一个疑惑。
    压缩算法是不是也用到了复制呢?因为我觉得在压缩的过程中,也需要把存活的内存进行转移,而转移也就是复制吧?
    麻烦老师给回答一下~

    作者回复: 确实是需要复制数据,这样起名主要是为了区分复制到同一个区域中(需要复杂的算法保证引用能够正确更新),还是复制到另一个区域中(可以复制完后统一更新引用)。

    
     1
  • 浪迹江湖
    2018-09-26
    突发奇想:如果 GC 将引用计数算法和可达性分析算法结合起来使用会怎样?

    循环引用毕竟是少数,如果先用引用计数算法回收掉大部分对象,再对剩余的小部分对象采用可达性分析算法解决循环引用问题。可能比只使用可达性分析算法带来更好的回收效率。

    作者回复: 赞想法!不过我认为没有达到更好的回收效率,因为垃圾回收标记的是非垃圾,剩余没有标记的对象是垃圾。用引用计数法清理后,可达性分析仍需遍历所有活着的对象。

    但是可以将引用计数做成minor minor GC,只有当引用计数回收不了垃圾时,再触发可达性分析。感兴趣的话可以深入探索一下业界其他非Java runtime的垃圾回收算法。

    
     1
我们在线,来聊聊吧