划分
类加载
- 将类的字节码载入方法区中,内部采用 C++ 的 instanceKlass 描述 java 类,它的重要 field 有:
- _java_mirror 即 java 的类镜像,例如对 String 来说,就是 String.class,作用是把 klass 暴露给 java 使用
- _super 即父类
- _fields 即成员变量
- _methods 即方法
- _constants 即常量池
- _class_loader 即类加载器
- _vtable 虚方法表
- _itable 接口方法表
- 如果这个类还有父类没有加载,先加载父类,加载和链接可能是交替运行的
其他
- 常量池
- 在字节码中会调用一些#1或者#2等引用,这些引用就是引用的常量池里的内容。
- 运行时常量池
- 常量池指的是.class文件中的内容,是静态的,而运行时常量池就是经过加载之后的class,能够找到直接的内存地址,引用包括变量引用,还有方法引用,但是字节码会放到方法区。
- 字符串常量池
- 即stringTable,也是类似于HashMap的存储,采用数组+链表的方式(因为不放置重复的字符串),设置虚拟机参数
-XX:+PrintStringTableStatistics
可以在控制台输出字符串常量池信息,
- 即stringTable,也是类似于HashMap的存储,采用数组+链表的方式(因为不放置重复的字符串),设置虚拟机参数
JVM的虚拟机栈
每个线程都会有一个虚拟机栈,栈中会有多个栈帧,举个例子,下面的代码创建了两个线程t1和t2,此时就会使用两个虚拟机栈,在IDEA中可以看到栈帧结构,如下图所示,当前线程最顶层栈帧都是
add
方法,栈帧的概念结构如下。栈帧的概念结构:
代码:
@Slf4j public class MyTest { public static void main(String[] args) throws ExecutionException, InterruptedException { new Thread(() -> { while (true) { for (int i = 0; i < 10000000; i++) { add(i, 1); } log.debug("t1"); } }, "t1").start(); new Thread(() -> { while (true) { for (int i = 0; i < 10000000; i++) { add(i, 1); } log.debug("t2"); } }, "t2").start(); } public static int add(int a, int b) { return a + b; // 在此行打断点,Suspend类型设置为Thread, } }