JVM 相关知识
一、JVM内存
以java1.8为例
必会!自己说出JVM内存中有哪些部分
1.运行时区域:
线程共有的:堆,线程独自有的:虚拟机栈,pc,本地方法栈(存放native方法)
堆中有: 字符串常量池,静态变量,
堆可以分为新生代、老年代、元空间
2.本地内存:
方法区和直接内存区
方法区是一个概念性的抽象,其实现有,元空间(有运行时常量池(字符串常量的符号引用等),方法区作用:将加载的Class文件中的类信息、字段信息、方法信息、常量、静态变量、符号引用等数据,存储到方法区中!!

举例:
package com.example;
// ① 类的完整名称、父类、接口等元数据信息
public class Demo {
// ② 运行时常量池中的符号引用和常量
public static final String CONST_STR = "Hello, Method Area";
public static final int CONST_INT = 100;
// ③ 静态变量(存放在方法区,对应内存中有实际存储空间)
public static int counter = 0;
private static Object sharedObj;
// ④ 实例变量(存放在堆中,每实例一份)
private int id;
private String name;
// ⑤ 静态初始化块(<clinit> 方法的一部分,在类初始化时执行)
static {
sharedObj = new Object();
counter = 10;
}
// ⑥ 构造器和普通方法的字节码(方法区存储方法元数据和字节码)
public Demo(int id, String name) {
this.id = id;
this.name = name;
}
public void sayHello() {
System.out.println(CONST_STR + ", I'm " + name);
}
// ⑦ 静态方法字节码也存放在方法区
public static void resetCounter() {
counter = 0;
}
public static void main(String[] args) {
Demo d = new Demo();
d.sayHello(); // ← 这里就是一个符号引用 to com.example.Demo.sayHello:()V
}
}


Constant pool:
#10 = Methodref #3.#17 // com/example/Demo."<init>":()V
#11 = Methodref #3.#18 // com/example/Demo.sayHello:()V
#17 = NameAndType #19:#20 // "<init>":()V
#18 = NameAndType #21:#22 // "sayHello":()V
#19 = Utf8 <init>
#20 = Utf8 ()V
#21 = Utf8 sayHello
#22 = Utf8 ()V
...
其中#11 = Methodref #3.#18 就是一个 符号引用,指向常量池中表示类索引 #3(com/example/Demo)和名字/描述符索引 #18(sayHello()V)的项。
在字节码中,调用 d.sayHello() 会编译为一条 invokevirtual #11 指令。
动态链接(解析)流程:
执行到 invokevirtual #11
JVM 首次遇到这条字节码时,看见常量池索引 #11,发现还没被解析。
解析阶段(Resolution)
JVM 查找常量池里 #11 指向的符号引用:
拿到类索引(#3 → com/example/Demo),确保该类已加载、已验证、已准备;
拿到名字/描述符索引(#18 → sayHello:()V),在 Demo 的方法表中查找对应方法。
查到后,JVM 会在运行时常量池的这个槽位(#11)上缓存一个直接引用(通常是指向方法区里 Demo.sayHello 方法实现的入口点、或者是一张跳转/虚方法查找表中的索引)。
后续调用
下一次再遇到 invokevirtual #11,JVM 不再去查符号引用,而是直接跳转到缓存好的本地代码地址(或通过 vtable 一次间接跳转),省去了符号解析开销。
二、JVM垃圾回收
- 与堆密切相关
堆中存放着对象,(对象头、实例数据、填充)
对象头
Mark Word:存储对象的运行时数据,如哈希码(hashCode)、GC 分代年龄、锁信息(偏向锁、轻量级锁、重量级锁)等。
Class Pointer(也叫 Klass Word):指向对象的类型元数据(方法区/元空间中的类结构),用来支持类型检查、方法调用等。
实例数据(Instance Data)
也就是你在类中定义的各个实例字段(非 static 的字段)。
对于继承关系,父类的实例字段会先于子类字段排列。
对齐填充(Padding / Alignment)
HotSpot 为了提高访问效率,会把对象大小向 8 字节边界(或更高、视架构而定)对齐。
- 可达性分析算法
首先明确:小对象1先放入新生代区中,当后续再new一个对象时检查新生代区是否满,满了则发起一次 Minor GC,将原始的小对象1存入老年代区;没满的话小对象1的年龄+1,当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中
大对象(比如:字符串、数组)直接放入老年代区
可达性分析算法思想:

Object 6 ~ Object 10 之间虽有引用关系,但它们到 GC Roots 不可达,因此为需要被回收的对象。
哪些对象可以作为 GC Roots?
3.垃圾回收算法:
(1)标记清除
(2)标记复制
(3)标记整理
(4)分代收集
根据各个年代的特点选择合适的之前的某种收集算法中。

浙公网安备 33010602011771号