- 空闲列表
空闲列表是在Java堆内存不完整的情况下使用的方式,已使用内存与空闲内存无规则,并且JVM另外维护了一张空闲内存的表,当有新对象需要分配内存时,就从空闲列表中查找一块足够该对象的内存。
- 处理并发安全问题;
当对象创建很频繁时,就需要去解决并发的问题,也就是线程安全。比如程序中多线程创建m和n两个对象,给m对象分配内存的同时也会给n对象分配,如果这时候两个对象分配的是同一块内存,必然就出现了冲突。 为了解决这个并发的问题,JVM提供了两种方式。
- CAS算法+失败重试方式
CAS是项乐观锁技术,当多个线程尝试同时更新一个变量时,只有其中一个线程能够更新变量的值,而其他的线程都是失败的,但失败的线程都不会被挂起,可以再次尝试,直到成功为止。
- 本地线程分配缓存区-TLAB
所谓本地线程分配缓存区,就是当线程开启时,就为每个线程在Eden区分配一块内存,然后当线程内部创建对象时,就从自己的内存空间分配。若自己的内存不足或者用尽时,就开始从堆内存中分配,这个时候就是采用CAS的方式。
- 初始化内存空间;
将分配到的内存,除对象头以外都初始化为零值。这也是为什么对象的实例在Java代码中不赋初始值就可以直接使用的原因,访问的都是对象的零值。
- 设置对象的对象头;
将对象的所属类,对象的HashCode以及对象的GC分代等数据存储到对象的对象头中。
- 执行init方法进行初始化。
执行init方法,初始化对象的成员变量,调用类的构造方法,到这里,一个对象就被创建了。
-
创建阶段,上面已经详细给出对象的创建过程;
-
应用阶段,当对象创建完成后,并分配给变量复制,状态切换到应用阶段;
-
不可见阶段,在程序中找不到对象的任何强引用;
-
不可达阶段,在程序中找不到对象的任何强引用,并且垃圾收集器发现对象不可达;
-
收集阶段,垃圾收集器发现对象不可达,并且垃圾收集器已经准备好对该对象的内存空间进行重新进行分配;
-
终结阶段,垃圾收集器回收该对象的空间。
1.3.1、判断对象是否需要被回收
在对对象进行回收前,需要知道该对象是否是垃圾。而判断一个对象是否需要被回收,有两种方式,引用计数法和可达性分析算法:
- 引用计数法
所谓引用计数法,指的是对象会维护一个引用计数器,计算被引用的次数,如果被引用一次,计数器就+1,如果不在引用,则-1,知道计数器为0时,就说明该对象可以被回收了。
如果堆中有两个对象相互引用,那他们的计数器都为1,就不会被回收,会造