应该会点JVM(二)

垃圾收集器与内存分配策略

为什么学习垃圾收集?

看起来jvm好像一切帮你做好,但是当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这种自动化的技术进行监控和调节。

垃圾回收区域

虚拟机栈,本地方法栈,程序计数器是线程私有的,和线程同生共死,当线程销毁时,内存自然回收,所以这部分不是考虑的重点。

所以研究重点应该在方法区和堆,而方法区的回收效率较低,重点在

引用计数

对象有一个引用计数器 new String()
有引用,计数器加一,String jiajun=new String()
引用失效,计数器减一,jiajun=null;

出现一个问题

Person jia=new Persoon();
Person jun=new Person();
jia.bro=jun;
jun.bro=jia;
jia=null;
jun=null;

此时虽然我们没有办法用jia和jun这两个对象,也就是这个是垃圾了,但是两个对象又互相引用,如果用这种算法是无法进行回收

可达性分析

扫描二维码关注公众号,回复: 2149820 查看本文章

GC Roots的对象:虚拟机栈中引用的对象(比如方法中定义的对象),本地方法栈中引用的对象,方法区中类静态属性引用的对象(static),方法区中常量应用的对象(final)

通过GC Roots对象作为起点,当GC Roots到一个对象没有引用链的话,那么就证明这个而对象不可用(如下图)


垃圾收集算法

标记清除

确定回收对象,进行标记,然后回收标记的对象
一个问题是标记清除效率不高
一个问题是标记清除后产生大量不连续的内存碎片,但需要分配较大对象的时候,因为没有足够大的连续空间分配给此对象,此时会触发另一次垃圾收集

复制

解决内存碎片的问题


将内存分为等大的A区和B区,创建对象时,存放于A区,当A区空间用完之后,将A区存活的对象复制到B区,然后A区清空,这样的话,就避免了内存碎片的问题


但是又有一个问题,这个时候我们只用到了一半的空间,所以我们要向办法提高空间利用率
研究发现,新生代对象大多都是朝生夕死,也就是存活的对象不多,那么我们就没必要分配一半的空间用于“粘贴”


所以虚拟机将新生代分为Eden和Surivior两个区,比例为8:1:1,可用的内存为一个伊甸区个一个存活区,一个存活区用于“粘贴,”,也就是新生代可用内存空间为容量的90%,这样的话就提高了空间了利用率


但是又有一个问题,如果这一个存活区存放不了复制的的对象,那么怎么办?于是,如果这些对象放不下,将直接进入另一块区域老年代

标记整理

对于朝生夕死的新生代来说,复制算法是不错的选择。但是对于存活率高的对象不是很好的选择,因为要进行较多的复制操作,效率会降低
过程:确定回收对象,进行标记,让存活的对象向一端移动,然后清理掉端边界以外的内存
那么这样的话,不会有内存碎片的问题,也没有复制过多效率降低的问题

分代收集

上面几种方法的综合利用
根据新生代和老年代的特点,分别选用适用的算法。
新生代存活率,那么可以选择复制算法
老年代存活率高,可以采用标记清理或标记整理算法

内存分配与回收策略

  • Minor GC,新生代GC,回收速度快
    Major GC/ Full GC , 收集整个堆,包括yong gen,old gen,perm gen,回收速度慢

猜你喜欢

转载自blog.csdn.net/lianhao19900202/article/details/78953366