程序员

深入理解jvm之gc

2020-09-16  本文已影响0人  也是只小可爱呢

垃圾回收 garbage collection GC

   首先垃圾回收比java出现之前还要早。

   现在考虑的是jvm里面的垃圾回收,首先jvm里的本地方法栈(存有与native方法相关的)、虚拟机栈(里面有对象的引用等)、程序计数器(记录了 当前线程正在运行的字节码的行号)随线程创建而创建,由于程序计数器不会出现内存溢出,然后另外两个栈起始大小会被虚拟机设定,线程完毕后这三也随之毁灭。

   所以,多个线程共享的方法区(已被加载的类的二进制文件、静态变量、常量(存在常量池内)等)、java堆(对象的实例、等)里面的内容被多个线程共享使用,什么时候会被回收,这个就是个问题,那怎么被回收?等等好多问题。

什么时候会被回收?

   jvm根据可达性分析算法判断这个是否需要回收。
   可达性分析算法其实是判断当前这块是否跟一个叫做gc roots有关联,如果能关联到,就表明还在使用,不然就认为应该回收。

   选择哪些作为gc roots也是问题?
   由于已经知道本地方法栈虚拟机栈是随着线程毁灭的,所以,如果当前判断的这个对象如果跟某个线程的本地方法栈和虚拟机栈内的引用的对象有关联,说明这个线程还没完,说明正在使用。那么gc roots应该虚拟机栈引用的对象本地方法栈jni引用的对象
   然后在方法区内有静态属性和常量,如果一个对象跟静态属性引用的对象有关联或者跟常量引用的对象有关联,说明这个对象也可能还是活的。

   因此,gc roots包含:

   还一个是引用计数法(jvm不用反正)。就是有个被引用的就+1.等于0表示不会再用了。

   其中【引用】用于存储对象的地址,可以分类为 强引用、软引用、弱引用、虚引用。
强度级别弱引用以下 每次触发gc时就回收。软引用 是将发生内存溢出时的gc会回收。

怎么回收的?

回收算法

垃圾回收器

serial回收器(新生代)

单线程收集器 stop the world暂停用户线程。Serial复制+Serial Old标记整理。

parNew(新生代)

serial的多条线程并行执行的版本。也是stop the world。parNew复制+Serial Old标记整理。cms收集器合作的默认的新生代收集器是parNew。

parallel Scavenge(新生代)

多条线程并行的,复制算法,跟parNew类似。parrallel S+parallel Old 。通过调节设置最大gc停顿时间或者吞吐量大小来控制吞吐量大小,即运行代码时间/(运行代码时间+gc时间)。吞吐量默认是99%。

Serial Old(老年代)parallel Old(老年代)

cms(老年代)

标记-清除

g1
并行并发,分代收集,局部复制,整体标记整理,维护一个优先列表,优先回收价值最大的区域。生成或者改变一个引用时,会用remember set记录这个引用是否在不同region。后面进行回收的时候,gc roots 范围会加入remember set里的范围。

举例子:

一个创建对象触发新生代垃圾回收的过程

    serial和serial old收集器,老年代10m,新生代10m 8:1:1,要依次生成三个2m的对象、一个4m的对象,在4m对象放进去的时候,jvm发现对应的新生代(8+1)放不下对应的4m对象了,触发minor gc。然后就是把这里的6m的存活对象放到 其中一个survivor去,发现还是放不下,咋办,就直接把这些存活的放到老年代去。然后,4m对象创建在了新生代的eden区。

   但是如果设置了大对象参数,就是会在给对象分配内存时判断当前的对象如果大于这个数,那么它就会直接在老年代内创建。不会触发minor gc。

哪些对象会出现在老年代内?

full gc 啥时候会触发?

上一篇 下一篇

猜你喜欢

热点阅读