learn-message-jvm
文章目录
java 对象头
在 Java 虚拟机中,每个 Java 对象都有一个对象头(object header),这个由标记字段和类型指针所构成。其中,标记字段用以存储 Java 虚拟机有关该对象的运行数据,如哈希码、GC 信息以及锁信息,而类型指针则指向该对象的类。
在 64 位的 Java 虚拟机中,对象头的标记字段占 64 位,而类型指针又占了 64 位。也就是说,每一个 Java 对象在内存中的额外开销就是 16 个字节。以 Integer 类为例,它仅有一个 int 类型的私有字段,占 4 个字节。因此,每一个 Integer 对象的额外内存开销至少是 400%。这也是为什么 Java 要引入基本类型的原因之一
如果虚拟机开启了压缩指针, 可以把类型指针 从 8 个字节压缩到 4 个字节, 从而对象头总共占用 12 字节
Java 虚拟机会让不同的 @Contended 字段处于独立的缓存行中,因此你会看到大量的空间被浪费掉。
GC
那么什么是 GC Roots 呢?我们可以暂时理解为由堆外指向堆内的引用,一般而言,GC Roots 包括(但不限于)如下几种:
- Java 方法栈桢中的局部变量;
- 已加载类的静态变量;
- JNI handles;
- 已启动且未停止的 Java 线程
jvm 链接
Java中继承类的初始化顺序可以总结为以下几点:
父类静态代码块的初始化。父类的静态代码块在类被加载时执行,且仅执行一次。
子类静态代码块的初始化。子类的静态代码块在类被加载时执行,且仅执行一次。
父类实例变量的初始化。在父类构造函数被调用之前,父类的实例变量被初始化。
父类构造函数的初始化。在父类实例变量被初始化之后,父类的构造函数被调用。
子类实例变量的初始化。在子类构造函数被调用之前,子类的实例变量被初始化。
子类构造函数的初始化。在子类实例变量被初始化之后,子类的构造函数被调用。
需要注意的是,当创建子类对象时,以上顺序逐步执行,以确保父类的初始化顺序在子类之前完成。同时,如果子类没有显示地调用父类构造函数,则默认调用父类的无参构造函数。
自己模拟虚拟机溢出场景
jvm 工具
- gceasy
- MAT
- GCViewer
- GCViewer
|
|
查看进程的内存分布情况
|
|
垃圾收集器
双亲委派机制及其打破情况
文章作者 DaleyZou
上次更新 2023-04-17