JVM定义
JVM体系结构概述
类装载器(ClassLoader)
执行引擎(Execution Engine)
本地接口(Native Interface)
Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。 主要是调用c或c++实现的本地接口
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合 C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为Native的代码,它的具体做法是Native Method Stack中登记Native方法,在Execution Engine 执行时加载Native libraries。
目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等等,不多做介绍。
运行时数据区(Runtime Data Area)
JVM内存区域
线程私有
Java虚拟机栈
- 线程执行了一个方法,就会对这个方法调用创建对应的一个栈帧
- 栈帧中存储了 方法的局部变量表、操作数栈、动态链接、方法出口(方法的返回地址)等信息。
- 局部变量表
- 用于存储方法参数和方法内部定义的局部变量。
- 操作数栈
- 可以理解为PC寄存器:用于作为计算过程的临时数据存储区。
- 临时数据指的变量对应的具体值 eg:int a=1; 对应的是1这个值
- CPU执行load命令时能将数据加载到操作数栈。
- 可以理解为PC寄存器:用于作为计算过程的临时数据存储区。
- 动态链接:是在程序运行期间完成的将符号引用替换为直接引用
- 方法返回地址
- 方法退出之后都需要返回方法被调用的位置。
- 方法退出之后都需要返回方法被调用的位置。
- 局部变量表
- 栈的生命周期(线程生命周期一致)
- 不存在垃圾回收的问题
- 可能的异常信息( java.lang.StackOverflowError)
本地方法栈
程序计数器
- 每个线程都有一个程序计数器
- 用来记录当前执行的字节码指令的位置的(行到了哪一条字节码指令)
线程共享
方法区 -》永久代(Meta Space) | 元数据空间
- JVM规范层面的东西
- jdk1.7 叫做方法区(永久带permGenspace) ;JDK 1.8 + 叫做 方法区( “Metaspace”(元数据空间))
- 永久带或metaspace是对方法区的不同实现,是实现层面的东西。
- 存储被jvm加载的类的结构信息、常量、静态变量、编译器编译后的代码等
- 类结构信息:类的名称、方法、字段等信息。
在传统的Java虚拟机中,.class
文件在加载时会被存储在永久代(Permanent Generation)中。永久代是Java虚拟机的一部分,用于存储类的元数据信息,包括类的结构、方法、字段等信息。这意味着在传统的Java虚拟机中,加载的类信息(包括字节码)将占用永久代的空间。
然而,从Java 8开始,永久代被移除,取而代之的是元空间(Metaspace)。在元空间中,类的元数据信息将被动态地分配和管理内存,而不再受到永久代的限制。因此,.class
文件的内容会被加载到元空间中。
总体而言,具体的存储位置取决于Java虚拟机的实现版本,而在现代的Java虚拟机中,元空间是类元数据信息的存储区域。
Java堆
4.3 完整流程
JVM内存参数设置
- -XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N
- -XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
- -XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M,达到该值就会触发 full gc进行类型卸载, 同时收集器会对该值进行调整:(动态调整)
- 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超 过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,- XX:PermSize代表永久代的初始容量。
- 由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生 了大小调整,基于这种情况,
- 一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大, 对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。