(二)JVM对象的分配和垃圾回收机制

484 阅读5分钟

一、JVM对象创建过程

image.png

1.检查加载

检查这条指令的参数是否在常量池中定位到一个类的符号引用。并检查该类是否被加载解析初始化过。

符号引用:用一组符号来描述所引用的目标。JAVA在编译的时候,每个java类都会编译成一个.class文件,但在编译的时候虚拟机是不会知道所引用的类的实际地址的,所以就用符号引用来代替。而在类的解析阶段则会把符号引用替换为真实的地址。

2.分配内存:

分配内存需要处理的两大问题:内存划分的方式、并发处理如何安全。

1) 划分内存的方式:指针碰撞、空闲列表

指针碰撞(规整的内存):

image.png

空闲列表(不规整的内存):

image.png

2)解决并发安全:CAS失败重试、本地线程分配缓冲(TLAB)。

CAS失败重试:

image.png

TLAB:

image.png

3.内存空间初始化。

成员变量赋初值。

4.设置对象头。

对齐填充:对象所占空间需要8字节的整数倍。

image.png

5.对象初始化。

执行构造方法。

二、对象的访问定位

1.句柄。

在堆中有句柄池,在操作数栈里保存的引用是指向句柄池的。然后再通过句柄池找到真实的对象。

优点:当进行内存整理的时候,在操作数栈中的地址可以不进行改变,依然指向句柄池,只不过句柄池对应的对象地址发生了变换。

缺点:耗时需要进行二次转换。

image.png

2.直接指针。(hotspot使用)

操作数栈的对象地址直接是对象的真实地址。

优点:查找速度快。

缺点:当对象地址改变了,需要改变线程里的对象地址。

image.png

三、垃圾收集器。

1.判断对象的存活

核心:有用,且可以执行。

1)引用计数法。

问题:两个对象相互引用。

python用的这个算法:通过额外启动一个线程来解决这个问题。

2)根可达算法

roots:root set(根的集合)

gcroots:一般是静态变量、线程栈里局部变量表里的变量、常量池、JNI(指针)

扩展:

1) 内部引用:class对象、异常对象、类加载器

2)同步锁:synchronized(对象) 锁里的对象。

3)内部对象:

4)临时对象:跨代引用(老年代持有新生代对象的引用)

image.png

面试题:CLASS对象能被回收么?

1. 这个class对象不能有实例对象。
2. 这个类的类加载器被回收了。(因为类加载器会持有创建这个class对象的引用)
3. class对象没有没有在任何地方引用,并且没有被反射使用。
4.参数控制:允许回收class对象。

2.finalize()方法。

当一个对象不满足根可达的时候,当内存不足的时候,会调用finalize方法一次。如果在内部重新变成可达,则不会被回收(理论上的)。当再次不可达便不会进入这个方法了,会直接被垃圾收集器回收掉。

但这个方法的执行线程优先级很低,很多时候对象已经被回收了才会执行这个方法,已经为时已晚。

3.各种引用

1)强引用:不会被回收。

2)软引用:当内存不足的时候(将要OOM),会被回收。

3)弱引用:当进行垃圾回收的时候就会被回收。

4)虚引用:通过此引用无法获得对象。

4. 对象分配策略

对象的分配技术:1)对象分配原则。 2)虚拟机的优化技术。

1.对象的分配原则

  • 对象优先在Eden区分配
  • 空间分配担保:新生代升级进入老年代默认老年代是放的下的。如果老年代放不在再进行fullgc.担保的范围根据每次fullgc的回收量带动态计算。
  • 大对象直接进入老年代:serial、parnew垃圾回收器才会有这个行为>4M。
  • 长期存活的对象进入老年代。最大是15,CMS默认是6.
  • 动态对象年龄判断。

image.png

1)先根据逃逸算法,判断对象是否逃逸,如果没有逃逸,则进行标量替换,把对象拆分到栈里。
2)逃逸了,则判断对象是否是大对象,如果是大对象,则把大对象直接放入老年代。
3)如果不是大对象,优先往TLAB里创建对象。
4)如果TLAB里放不下,则放入Eden区。

2.虚拟机的优化技术

  • 逃逸分析 + 触发jit(热点数据) -> 满足两点才能进行栈上分配。
  • 本地线程分配缓冲

5.垃圾回收算法

复制算法、标记清除算法、标记整理算法

1)复制算法

image.png

特点:(用于新生代的幸存者0,1区)

  • 实现简单运行效率高。
  • 没有内存碎片。
  • 利用率只有一半。

appel式回收(新生代的划分方式)

因为绝大部分都是垃圾。所以新生代划分是8:1:1的比例。(空间利用率百分之90)

2)标记清除算法

image.png

特点:

  • 位置不连续,产生碎片。
  • 可以做到不暂停

3)标记整理算法

image.png

特点:(使用的标记整理算法是先整理再清除)

  • 没有内存碎片。
  • 指针需要移动,耗时。