# jAVA 初识jvm(四)
jAVA 初识jvm(四)
运行时数据区域(Running data area)
运行数据区域结构如图所示:
1.方法区、堆栈对应的是一个进程。程序计数器、本地方法栈、虚拟机栈对应的是线程。线程间共享堆、堆外内存(方法区、代码缓存)。
2.一个运行时数据区域相当于一个唯一的Runtime类的实例。Runtime是单例的。
程序计数器(Pc寄存器)
1.Pc寄存器是用来存储指向下一条指令的地址(即将执行的指令),执行引擎根据Pc寄存器指向的指令地址取指令。运行速度快。
2.每个线程有一个Pc寄存器,是线程私有的,会存储当前线程正在执行的java方法的指令地址。
3.相当于数据库中的游标,类似于集合的迭代器。没有Gc、OOM(OutMerryError)。
具体的Pcj寄存器实现如下:执行引擎会读取寄存器的地址。执行引擎操作虚拟机栈、局部变量表,翻译成机器指令,让对应的CPU进行运算。
- Pc寄存器存储指令地址有什么用?
因为Cpu需要切换不同的线程,记录执行的位置,当线程切换后需要明确执行到的位置。 - Pc寄存器为什么设置成线程私有的?
为了能够准确的记录各个线程的字节码指令地址。
本地方法栈
本地方法(Native修饰的方法)
Native Method就是一个java调用非Java代码的接口。比如调用C方法。本地接口的作用是融合不同的编程语言为Java所用。
- 为什么使用Native Method?
与Java环境外交互、与操作系统交互、Sun的解释器是C语言实现的。
1.Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用。
2.本地方法栈是线程私有的。
3.栈的大小可固定、扩展。
4.本地方法是用C语言实现的。
5.如果需要调用本地方法(Native Method)的时候,在本地方法栈中登记。
虚拟机栈
- 栈溢出的情况?(StackOverflowError)
通过-Xss设置栈的大小,调整栈的大小,不能保证不出现栈溢出。 - 垃圾回收会涉及到虚拟机栈吗?
不会涉及Gc
1.栈是运行时的单位:程序如何执行、如何处理数据。每个线程创建的时候回创建一个栈,是线程私有的。保存的是一个一个的栈帧。
2.作用:保存方法的局部变量(8中基本数据类型、对象的引用地址)、部分结果、并参与方法的调用和返回。
3.栈的优点:访问速度仅此于程序计数器,只有进栈和出栈操作。对于栈来说不存在垃圾回收问题,存在OOM(内存溢出)问题。
- 栈大小:栈的大小会溢出
-Xss
调节栈的大小
栈的存储单位
1.栈帧是栈的存储单位,方法和栈帧是一一对应的。
2.不同线程的栈帧是不能相互引用的。
栈帧的内部结构
- 局部变量表(Local Variables):最基本的存储单元是Slot(变量槽)
1.是一个数字数组。主要用于存储方法的参数、定义在方法体内的局部变量。
2.不存在安全问题。
3.局部变量所需要的容量的大小实在编译器确定下来的。
-
操作数栈(Operand Stack)
-
动态链接(Dynamic Linking)
-
方法返回地址(Return Adress)
-
一些附加信息
堆
1.一个Jvm实例只存在一个堆内存,堆也是Java内存管理的核心区域。
2.Java堆区在Jvm启动的时候被创建。是Jvm管理的最大一块内存空间。堆的内存大小是可以调节的。
3.堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。
4.所有的线程共享Java堆。
5.几乎所有的对象实例都在堆上分配内存。数组和对象永远不会存储在栈上,因为栈中保存引用,这个引用指向对象或者数组在堆中的位置。
6.堆是Gc执行垃圾回收的重点区域。
内存细分
- 新生区:绝大部分对象的创建销毁是在新生区完成的。
- 养老区
- 元空间(Jdk8及之后)
堆空间大小设置
1.-Xms
堆区的起始内存
2.-Xmx
堆区的最大内存
3.一旦堆区中的内存大小超过-Xmx所指定的最大内存时候,将会抛出内存溢出。
4.默认情况下,初始内存为物理电脑内存大小/64,最大内存大小为物理电脑内存大小/4。
对象分配过程
1.new的对象先放在伊甸园区。此区有大小限制。
2.伊甸园填满时候调用Minor Gc(年轻代的垃圾回收),之后判断是否是垃圾。经过一次Gc后将剩下的对象放到S1(幸存者区1)。伊甸园区又满了之后又进行Gc,将对象放在S2(幸存者2区)
- 关于幸存者区域,谁空谁是to。
- 关于垃圾回收:频繁在新生区域收集,很少在养老区,几乎不再永久代收集。
方法区
1.方法区是由多个线程共享,存储运行时的常量池、一些特殊的方法。
2.方法区在JVM启动的时候被创建
3.方法区的大小,和堆空间一样,可以固定也可以扩展。
4.方法区的大小可以决定保存多少个类。如果系统定义了太多的类,导致方法区溢出。
5.关闭Jvm就会释放这个区域的内存。
方法区的内存结构
存储被虚拟机加载的类型信息、静态变量、常量、及时编译器编译后的缓存等。