JVM————虚拟机的内存分配
一、堆
在虚拟机初始化时创建,初始化对象和成员变量,所有的对象和数组都要在堆上分配
关于堆的分代
堆通常可分为新生代和老年代,新生代包括1个Eden和两个Survivor区,Survivor区又包括from区和to区。
minnor GC from区中的数据会和to区进行复制算法,交换数据,当次数满15次会发生full GC将数据移动到老年区
为什么最大age是15?
因为对象的年龄存放在对象中,占4bit最多表示16个数,年龄为0-15
分代的原因是为了减少STW的次数提高系统的吞吐量
二、方法区
jdk1.8之后为元空间,存放常量,静态变量,类元信息(类的组成信息)
方法区内还有运行时常量池
用于存放静态编译产生的字面量和符号引用。
该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。
三、栈
1、虚拟机栈(栈内存)
虚拟机栈是由栈帧组成
栈帧有四部分组成
(1)局部变量表
a=1;
a=2;
基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定。
(2)操作数栈
用来存储运算结果以及运算的操作数,它不同于局部变量表通过索引来访问,而是压栈和出栈的方式
(3)动态链接
Math math = new Math();
math.compute();
程序在运行过程中,通过Math对象的对象头,对象头指向方法区的类元信息动态链接就是符号引用在程序运行过程中根据对象的头指针找到这个方法所对应的入口的内存地址,把这个地址存放到动态链接中将符号引用在程序运行过程中转变为直接引用
(4)方法出口
return的值
2、本地方法栈
native()
启动一个线程start方法的源码里面会调用start0()方法,它就是一个native方法,然后再通过C语言或者C++实现找.dll文件去实现C语言本地方法的局部变量就存放在jvm的本地方法栈中
四、程序计数器
每个程序计数器都是不同的线程,表示执行当前线程的字节码指令(地址)的行号
该内存区域是唯一一个java虚拟机规范没有规定任何OOM情况的区域。