划分

  • 图片说明

类加载

  • 将类的字节码载入方法区中,内部采用 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可以在控制台输出字符串常量池信息,

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,
            }
        }