内存结构
程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。
JVM 虚拟机栈:存放基本数据类型、对象的引用、方法出口等,线程私有。
本地方法栈:和虚拟栈相似,只不过它服务于Native方法,线程私有。
堆:java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享。
方法区:存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带),回收目标主要是常量池的回收和类型的卸载,各线程共享
执行 java 命令
-
创建 JVM,调用类加载子系统加载 class,将类的信息存入方法区
-
创建 main 线程,使用的内存区域是 JVM 虚拟机栈,开始执行 main 方法代码
-
如果遇到了未见过的类,会继续触发类加载过程,同样会存入方法区
-
需要创建对象,会使用堆内存来存储对象
-
不再使用的对象,会由垃圾回收器在内存不足时回收其内存
-
调用方法时,方法内的局部变量、方法参数所使用的是 JVM 虚拟机栈中的栈帧内存
-
调用方法时,先要到方法区获得到该方法的字节码指令,由解释器将字节码指令解释为机器码执行
-
调用方法时,会将要执行的指令行号读到程序计数器,这样当发生了线程切换,恢复时就可以从中断的位置继续
-
对于非 java 实现的方法调用,使用内存称为本地方法栈(见说明)
-
对于热点方法调用,或者频繁的循环代码,由 JIT 即时编译器将这些代码编译成机器码缓存,提高执行性能
特殊说明
- 对于 Oracle 的 Hotspot 虚拟机实现,不区分虚拟机栈和本地方法栈