一、as if serial
不管如何重排序,单线程执行结果不会变
二、对象的创建过程
三、对象占用多少字节
对象的MarkWord一般占8字节,MarkWord的2位来表示锁的状态,分代年龄也在MarkWord里,表明这个对象被GC回收了多少次
+ UseCompressedClassPointers和+ UserCompressedOops,这2个参数是JVM默认开启的
UseCompressedClassPointers会把_class pointer从8字节压缩到4字节
UserCompressedOops会压缩对象的引用类型的成员变量。如图,String本来应该是8字节,由于这个参数,被压缩到了4字节
MarkWord
为什么GC年龄默认为15 ?
可以看到分代年龄占4位,而4位最多表示16种状态: 0~15。所以年龄最大是15,是这么来的
调用hasCode导致锁升级
四、GC
何为垃圾
单一个对象没被引用的时候,这个对象就成了垃圾
怎么发现垃圾
引用计数器
说白了就是一个对象被引用了,计算器+1,这个对象没被引用,计数器变为0,就回收。
引用计数器无法解决循环引用,A引用B,B引用C,C引用A,那么这3个对象永远无法被回收
GC Root(可达性分析算法)
JVM采用的是GC Root
此算法的核心思想:通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为“引用链”,当一个对象到 GC Roots 没有任何的引用链相连时(从 GC Roots 到这个对象不可达)时,证明此对象不可用。以下图为例:
在Java语言中,可作为GC Roots的对象包含以下几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象。(可以理解为:引用栈帧中的本地变量表的所有对象)
- 方法区中静态属性引用的对象(可以理解为:引用方法区该静态属性的所有对象)
- 方法区中常量引用的对象(可以理解为:引用方法区中常量的所有对象)
- 本地方法栈中(Native方法)引用的对象(可以理解为:引用Native方法的所有对象)
GC算法
标记-清除算法
简单来说就是把没用的进行标记,然后清楚掉标记的
适用场景:存活对象比较多
缺点:需要进行2次扫描(一次标记,一次清除),容易产生内存碎片
复制算法
开辟一个新的空间,把存活的对象移动到新空间
适用场景:存活对象比较少的情况,因为涉及到了对象的移动,对象存活的少了,移动次数肯定少,效率自然高
标记-压缩
说白了就是把存活对象挤到一起,集中起来,然后剩下的垃圾对象直接清理
分代算法
分代算法其实跟垃圾回收器有关,ZGC之前所有的垃圾回收器都是分代算法。ZGC不在分年轻代和老年代
G1是逻辑分代,物理不分代