Java虚拟机JVM组成
Posted 白-胖-子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java虚拟机JVM组成相关的知识,希望对你有一定的参考价值。
JVM
- Java虚拟机。
- Java程序源代码编译为中间码即字节码后,再运行在JVM之上。
- JDK 使用Oracle官方Java虚拟机HotSpot VM
- 安卓 使用Google自研Java虚拟机Dalvid
JVM 组成部分
Class Loader Subsystem 类加载子系统:
- 使用Java语言编写.java Source Code文件,通过javac编译成.class Byte Code文件。
- class loader类加载器将所需所有类加载到内存,必要时将class类实例化成实例
- 把一个具体的class模板生成一个具体的资源叫做实例化
Runtime Data Areas 运行时数据区:
- java运行时的内存空间
- 最消耗内存的空间,需要优化
- JVM运行时数据区域由下面部分构成:
- Method Area
- Heap
- Java stack
- Program Counter Register
- Native Method Stack
1. Method Area 方法区域 元空间(JDK8) (线程共享):
- 方法区是所有线程共享的内存空间,存放已加载的类信息(构造方法,接口定义),常量(final),静态变量(static), 运行时常量池等。
- 实例变量并不存放在方法区域,存放在堆内存中。
- 从JDK8开始此空间由永久代改名为元空间。
2. Heap 堆 (线程共享):
- 堆在虚拟机启动时创建,存放创建的所有对象信息。
- 如果对象无法申请到可用内存将抛出OOM异常.
- 堆是靠GC垃圾回收器管理的,通过-Xmx -Xms 指定最大堆和最小堆空间大小
- 存放的都是大的资源
- 由class类生成的对象,意为实例,存放的空间
- FIFPO先进先出,吃多了上厕所
- 堆内经常创建和销毁对象,内存也就经常使用和被销毁,会产生内存碎片
3. Java stack 私有栈 (线程私有):
- Java栈是每个线程会分配一个栈,存放java中8大基本数据类型,对象引用,实例的本地变量,方法参数和返回值等,
- 基于FILO()(First In Last Out),每个方法为一个栈帧
- java给每个线程分配一个栈
- 存放了对象引用实例和本地变量
- 基于FILO,先进后出,喝多了吐
4. Program Counter Register 程序(指针)计数器 (线程私有):
- PC寄存器就是一个指针,指向方法区中的方法字节码,每一个线程用于记录当前线程正在执行的字节码指令地址。
- 由执行引擎读取下一条指令。因为线程需要切换,当一个线程被切换回来需要执行的时候,知道执行到哪里了。
5. Native Method Stack 本地方法栈 (线程私有):
- 本地方法栈为本地方法执行构建的内存空间,存放本地方法执行时的局部变量、操作数等。
- 所谓本地方法,使用native 关健字修饰的方法,比如:Thread.sleep方法. 简单的说是非Java实现的方法,
- 例如操作系统的C编写的库提供的本地方法,Java调用这些本地方法接口执行。
- 本地方法应该避免直接编程使用,因为Java可能跨平台使用,如果用了Windows API,换到了Linux平台部署就有了问题。
Execution Engine 执行引擎:
- 包括JIT (Just-InTime-Compiler)即时编译器, GC垃圾回收器
JustInTimeCompiler (JIT) 即时编译器
- 即时编译器是一个把Java程序转换成二进制的程序。
- JIT编译是动态编译的一种。
- JIT编译(just-in-time compilation)是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。
- JIT 渲染引擎直接将网站最新内容从数据库渲染给访问用户
- 计数器超过阈值溢出,触发JIT编译。
Garbage Collection (GC) 垃圾回收器
- JVM垃圾收集器是JVM内存回收算法的具体实现,表现为具体的执行策略。
- JDK 1.8 默认的垃圾回收器:PS + ParallelOld,所以大多数都是针对此进行调优
代相关回收器
- 年轻代三个:Serial,PS,ParNew
- 老年代三个:Serial Old,PS Old,CMS,
- CMS号称200毫秒以内
- 单独的串行就不用了
- 年轻代和老年代配合使用
新生代串行收集器Serial:
- 单线程、独占式串行,采用复制算法,简单高效但会造成STW
新生代并行回收收集器PS(Parallel Scavenge):
- 多线程并行、独占式,会产生STW, 使用复制算法关注调整吞吐量,此收集器关注点是达到一个可控制的吞吐量
- Parallel Scavenge 收集器具有自适应调节策略,它可以将内存管理的调优任务交给虚拟机去完成。
- 自适应调节策略也是Parallel Scavenge与 ParNew 收集器的一个重要区别。
新生代并行收集器ParNew:
- 是Serial 收集器的多线程版,将单线程的串行收集器变成了多线程并行、独占式,使用复制算法,相当于PS的改进版
- 经常和CMS配合使用,关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,适合需要与用户交互的程序,良好的响应速度能提升用户体验
老年代串行收集器Serial Old:
- Serial Old是Serial收集器的老年代版本,单线程、独占式串行,回收算法使用标记压缩
老年代并行回收收集器Parallel Old:
- 多线程、独占式并行,回收算法使用标记压缩,关注调整吞吐量
- Parallel Old收集器是Parallel Scavenge 收集器的老年代版本,这个收集器是JDK1.6之后才开始提供
- Parallel Scavenge 收集器无法与CMS收集器配合工作,因为一个是为了吞吐量,一个是为了客户体验(也就是暂停时间的缩短)
老年代CMS 并发标记清除算法收集器 Concurrent Mark Sweep :
- 在某些阶段尽量使用和工作线程一起运行,减少STW时长(200ms以内), 提升响应速度,是互联网服务端BS系统上较佳的回收算法
- 分为4个阶段:初始标记、并发标记、重新标记、并发清除,在初始标记、重新标记时需要STW。
代无关回收器
- 新版本中不再区分年轻代和老年代
- G1 回收器 在Tomcat9已经作为默认回收期了达到10毫秒之内
G1收集器 Garbage First :
- 最新垃圾回收器,从JDK1.6实验性提供,JDK1.7发布,其设计目标是在多处理器、大内存服务器端提供优于CMS收集器的吞吐量和停顿控制的回收器。
- JDK9将G1设为默认的收集器,建议 JDK9版本以后使用。
- 基于标记压缩算法,不会产生大量的空间碎片,有利于程序的长期执行。
- 分为4个阶段:初始标记、并发标记、最终标记、筛选回收。并发标记并发执行,其它阶段STW只有GC线程并行执行。
- G1收集器是面向服务端的收集器,它的思想就是首先回收尽可能多的垃圾(这也是Garbage-First名字的由来)
- G1能充分的利用多CPU,多核环境下的硬件优势,使用多个CPU来缩短STW停顿的时间(10ms以内)。
- 可预测的停顿:这是G1相对于CMS的另一大优势,G1和CMS一样都是关注于降低停顿时间,但是G1能够让使用者明确的指定在一个M毫秒的时间片段内,消耗在垃圾收集的时间不得超过N毫秒。
- 通过-XX+UseG1GC选项指定使用G1
ZGC收集器: 减少SWT时长(1ms以内), 可以PK C++的效率,目前实验阶段
Shenandoah收集器: 和ZGC竞争关系,目前实验阶段
Epsilon收集器: 调试 JDK 使用,内部使用,不用于生产环境
Native Method Interface 本地方法接口:
- 将本地方法栈通过JNI(Java Native Interface)调用Native Method Libraries,
- 比如:C,C++库等,扩展Java功能,融合不同的编程语言为Java所用
- JVM与本地库的交互接口
以上是关于Java虚拟机JVM组成的主要内容,如果未能解决你的问题,请参考以下文章