Thread
Hotspot JVM 将Java线程一对一映射到操作系统原生线程上
- Java线程状态初始化,如thread-local sotrage, allocation buffers, synchronization objects, stacks, program counter
- 原生线程创建,调用run()方法
- run()方法返回,处理未捕获异常
- 线程终止,释放Java线程及原生线程资源,并判断JVM是否需要退出(如此线程是最后一个非守护线程)
JVM System Thread
由main方法创建的系统后台线程
VM thread
执行需要JVM在safe-point时才能执行的操作,如GC, thread stack dump, thread suspension, biased locking revocationPeriodic task thread
GC threads
Compiler threads
运行时编译字节码到native codeSignal dispatch thread
接收操作系统signal并处理
Per thread
与线程一一对应的资源
Program Counter (PC)
下一条指令或操作数的地址,如果是native方法,PC值为undefined
VM Stack
虚拟机栈,存储栈帧(Frame),每次方法调用时入栈,方法返回或异常时出栈。当栈容量超过最大限制时,会抛出StackOverflowError
异常,当新线程没有足够内存创建栈时,会抛出OutOfMemoryError
异常
Native Method Stack
本地方法栈,支持native方法执行,类似虚拟机栈,有的实现将两者合并
Stack Frame
栈帧(Stack Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。
栈帧随着方法调用而创建,随着方法结束(返回或抛出异常)而销毁。栈帧包含局部变量表(Local Variables Array)、操作数栈(Operand Stack)和指向当前方法所属的类的运行时常量池的引用。
Local Variable Array
方法调用时所有的局部变量,包括参数及对this的引用,局部变量可以是基本类型,引用及返回地址,其中long和double占用两个局部变量。当方法调用时,参数会传递至从0开始的连续位置中,如果是实例方法,0存储方法所在对象的应用(即this)。局部变量表是可重用的,超出作用域的变量的位置可以被新变量使用。局部变量表长度在编译器决定。Oprand Stack
用于字节码操作,性质类似CPU寄存器,例如调用iadd字节码指令会将栈顶两个int值出栈相加后再入栈Dynamic Linking (Reference to runtime constant pool)
C/C++代码在编译链接阶段会将符号引用(symbolic reference)转化为实际内存地址,对于Java来说,链接是在运行时动态进行的。Java class编译时,所有的变量及方法引用都以符号引用形式保存在class的常量池中,由JVM选择解析时机,eager/static 或者lazy/later resolution。解析只发生一次,同时会触发必要的类加载,解析后的direct reference以相对于方法或变量运行时位置存储结构的偏移量存储
Shared Between Threads
线程间共享的资源
Heap
存储对象实例及数组,栈帧被设计为创建后大小不可变,因此可变对象都存放在堆中,栈帧中仅保存基础类型及引用
Interned Strings
String常量池,在类加载时,所有的String常量都会被保存到常量池中。运行时也可以显式调用String.intern()
,如果常量池中已经存在该string,则直接返回引用,否则将该string加入常量池中并返回引用。
Java 6中String常量池放在Permgen中,容易引发OOM问题,Java 7开始已经将String常量池放到堆中,默认大小为60013,如果重度使用intern的话需要配置的更大避免hash冲突导致性能下降,详细信息参考String.intern in Java 6, 7 and 8
Non-Heap Memory
Method Area
方法区,保存每个类的结构信息,如运行时常量池,字段和方法数据,构造函数和普通方法的字节码等等,包括:
- Classloader Reference
- 相对应的classloader也会维护一份所有已加载类定义的引用
- Run Time Constant Pool
- Field data
- Method data
- Method code
Run Time Constant Pool
JVM为每个类维护一个运行时常量池,保存运行时所需的数据,数据类型如下:
- numeric literals
- string literals
- class references
- field references
- method references
字节码操作时会直接引用常量池中的数据,例如:
|
|
Code Cache
保存JIT编译后的本地代码,以前遇到过JDK的bug,Code Cache占用过高触发回收后JIT失效,因此可以考虑相对设置的大一些避免触发回收-XX:ReservedCodeCacheSize=256m
Class File Structure
|
|
测试代码
|
|
编译结果
|
|