JVM内存模型
- 栈
- 堆
- 方法区
- 程序计数器
- 本地方法栈
栈
每个线程私有,有几个线程就会有几个栈.栈也是一种数据结构,遵循FILO(先进后出),在线程创建执行方法时都会创建一个栈帧,进行压栈的操作.最先进行压栈的栈帧最后出来,最后压栈的栈帧最先出来.可以理解为栈是一个封住底的桶,而栈帧就是一个放入桶中,切面面积与桶相等的木块,你需要先取出后面放进去的木块,才能取出前面的.
栈帧中结构
在每个栈帧栈帧中都会存储几个常见的结构(我也不知道怎么讲) 如: 局部变量表,操作数栈,动态链接,方法出口(见图一).
- [1] 局部变量表 : 存储同一方法内的局部变量,如(int a,String str)这里的a和str.局部变量中的对象句柄有指向堆内存具体对象位置的指针
- [2] 操作数栈 : java文件会被编译为class字节码文件,字节码文件又会被翻译成机器码.操作数栈就是程序运行在执行JVM指令的时候,操作数的中转站(操作数栈也是一种栈结构).比如下例 int a = 1; int b = 2; int c = a+b;此时程序执行时会将1压入操作数栈,然后进行弹栈将1弹出来赋给a(第一行代码),然后将2压入栈,弹出2赋给b(第二行代码),将1和2压入栈(分两步进行),将1和2弹出栈,计算出结果3并赋值给c(第三行代码). java中任意数据类型都可以放入操作数栈,32位数据占据栈容量为1,64位占据栈容量为2.
- [3] 方法出口 : 记录着程序从什么时候进入这个方法,以便方法结束后,栈帧被弹出返回原程序执行位置.
- [4] 动态链接 : 在程序运行期间将常量池中的符号替换为直接引用
程序计数器
每个线程私有,记录着程序运行期间,jvm指令执行的行数.
本地方法栈
用于执行本地方法的栈,每个线程私有.在java中有很多底层方法用native修饰,这些方法就是本地方法,本地方法是用其他语言写的比如c.
堆
存放对象的位置.堆中分为年轻代和老年代.内存分配占比默认为1:2.在年轻代中分为Eden区,Survivor区(分为两部分,S0,S1),Eden:S0:S1:1:1.在对象新建之初对象会被放入Eden区,当这一区放满会触发Young GC,清理掉死亡对象,将剩余存活对象移入到S0区,S0区放满后依然会触发Young GC,并将剩余存活对象放入S1区,S1区满后依然会触发Young GC,并将剩余存活对象放回From区.
也就是说年轻代的三个分区在放满后都会触发,Young GC并移动剩余存活对象
方法区
方法区也叫元空间,存放着常量池,静态变量,类的元信息等.堆中的对象会指向方法区中对应的类的信息.