JVM包含以下三大部分:类加载器(Class Loader)
、执行引擎(Execution Engine)
、运行时数据区(Runtime Data Area)
。
类加载器是JVM的一个重要组成部分,负责将Java类加载到内存中并进行初始化。类加载器具有层次结构,分为不同的类加载器,每个加载器负责加载特定的类。以下是对JVM类加载器的详细解释:
Bootstrap Class Loader(启动类加载器):
java.lang
包中的类。Extension Class Loader(扩展类加载器):
jre/lib/ext
)中的JAR包和类。sun.misc.Launcher$ExtClassLoader
实现的,并继承自java.net.URLClassLoader
。Application Class Loader(应用类加载器):
sun.misc.Launcher$AppClassLoader
实现的,并继承自java.net.URLClassLoader
。自定义类加载器:
类加载过程:
加载(Loading): 类加载器根据类的全限定名找到类文件,将其加载到内存中。这个过程不包括类的实例化,只是将类的元数据加载到JVM中。
链接(Linking): 将已加载的类与其他类和资源连接起来。链接分为三个阶段:验证(Verification)、准备(Preparation)和解析(Resolution)。
初始化(Initialization): 对类进行初始化,执行类构造器 <clinit>
方法的过程。在初始化阶段,静态成员变量会被赋初始值,静态代码块会被执行。
双亲委派模型: JVM的类加载器采用了双亲委派模型,即在加载一个类时,会首先尝试由父加载器加载,如果父加载器无法加载,则由子加载器加载。这种模型保证了类的一致性和安全性。
类加载器在Java中具有重要作用,它使得Java应用程序能够动态加载类,实现了类的隔离和版本管理,同时也有助于确保类的安全性和合规性。
执行引擎是Java虚拟机(JVM)的一个重要组成部分,负责将编译后的字节码文件转化为机器代码并执行。它是实现Java程序运行的核心引擎,控制着程序的执行流程。以下是对执行引擎的详细解释:
字节码解释器(Bytecode Interpreter):
即时编译器(Just-In-Time Compiler,JIT Compiler):
执行流程:
执行引擎在Java虚拟机中扮演了至关重要的角色,它是将高级Java程序转化为底层机器代码的关键环节。字节码解释器和即时编译器在执行引擎中的共同作用,可以在保证跨平台特性的同时提供高效的执行性能。
运行时数据区(Runtime Data Area)是Java虚拟机(JVM)在运行Java程序时用来存储数据的区域,它包含了多个不同的内存区域,每个区域负责不同的任务和数据存储。以下是对运行时数据区各个区域的详细解释:
方法区(Method Area):
堆(Heap):
虚拟机栈(Java Virtual Machine Stacks):
本地方法栈(Native Method Stacks):
程序计数器(Program Counter):
运行时数据区是Java虚拟机运行程序时的重要组成部分,各个区域的功能和作用紧密相连,它们一起支持了Java程序的执行和管理。不同区域的管理和分配在不同的JVM实现中可能有所不同,但总体上符合Java虚拟机规范。
Java虚拟机(JVM)的堆内存是存储对象实例和数组的主要区域,它在运行时动态分配和管理内存。堆内存模型由新生代、老年代和持久代(或元空间)组成,每个区域负责不同类型的对象和垃圾回收。以下是对JVM堆内存模型各个区域的详细解释:
新生代(Young Generation):
老年代(Old Generation):
持久代(Permanent Generation)或元空间(Metaspace):
堆内存模型中的各个区域之间有对象的流动,对象从新生代的Eden空间开始分配,经过多次垃圾回收后,如果仍然存活,会晋升到老年代。垃圾回收的主要目标是清理无用的对象,以便为新对象的分配腾出空间,同时也是为了避免堆内存溢出。
不同的JVM实现可能在堆内存管理方面有所不同,但总体上遵循类似的内存模型,以支持Java程序的运行和内存管理。
垃圾回收(Garbage Collection)是Java虚拟机(JVM)自动管理内存的重要机制,它可以识别和清理不再被使用的对象,以回收内存并防止内存泄漏。垃圾回收器(Garbage Collector)负责执行垃圾回收的操作,而垃圾回收算法决定了具体如何标识和回收垃圾对象。以下是对垃圾回收器和垃圾回收算法的详细解释:
垃圾回收器:
垃圾回收器是执行垃圾回收操作的模块,负责找到不再使用的对象并将其释放以回收内存。不同的JVM实现可能有不同类型的垃圾回收器,以适应不同的应用场景。以下是常见的垃圾回收器:
Serial Garbage Collector:
Parallel Garbage Collector:
Concurrent Mark-Sweep (CMS) Garbage Collector:
G1 Garbage Collector:
ZGC收集器:
ZGC(Z Garbage Collector)收集器是oracle出版的一种低延迟的垃圾回收器,它的目标是将垃圾回收的停顿时间控制在10毫秒以内。ZGC收集器适用于对低延迟有较高要求的应用程序。
低停顿时间: ZGC的主要目标是实现低停顿时间。它通过在垃圾回收过程中与应用线程并发执行,减少了长时间的STW(Stop-The-World)暂停。大部分的垃圾回收操作都是并发执行的,最大的STW暂停时间通常只在几毫秒到十几毫秒之间。
分代内存布局: ZGC使用分代内存布局,分为新生代和老年代。新生代使用可并发复制算法,而老年代使用标记-整理算法。
压缩: 为了减少堆空间的碎片,ZGC回收器会在标记-整理阶段对存活对象进行压缩,使得内存空间更加连续。
可预测性: ZGC回收器设计时强调可预测性,尽量保证回收的时间是可控的,不会导致应用出现长时间的停顿。
适应大堆: ZGC适用于大内存堆环境,可以有效管理几个字节到数TB的内存,ZGC在JDK 11中引入,并在后续版本中逐渐得到改进和优化。
Shenandoah收集器:
Shenandoah收集器是Red Hat公司出版的一种并发垃圾回收器,它通过将垃圾回收的工作分散到多个线程中,实现了低停顿时间。Shenandoah垃圾回收器具有以下特点:
低停顿时间: Shenandoah的主要目标是实现非常低的停顿时间。它通过在大部分垃圾回收阶段与应用线程并发执行,最大程度地减少了长时间的STW(Stop-The-World)暂停。
并发性: Shenandoah回收器在许多阶段中与应用线程并发执行,这意味着应用线程可以在回收过程中继续工作,减少了应用的停顿。
分代内存布局: Shenandoah使用了分代内存布局,分为新生代和老年代。它使用并发复制算法来处理新生代,使用标记-整理算法来处理老年代。
堆压缩: Shenandoah回收器采用了堆压缩技术,以减少内存碎片,提高内存使用效率。
适用大堆: Shenandoah适用于大型的Java应用,可以有效管理数十GB甚至数百GB的堆内存,Shenandoah最早在JDK 12中以实验特性引入,在后续版本中继续得到改进和优化。
垃圾回收算法:
垃圾回收算法决定了如何标识和回收不再使用的对象,不同的算法有不同的策略和特点。
引用计数算法(Reference Counting):
可达性分析算法(Reachability Analysis):
分代收集算法(Generational Collection):
垃圾回收器和垃圾回收算法的选择取决于应用的性能需求、停顿时间要求、内存规模等因素。不同的应用可能需要不同的垃圾回收策略,以平衡性能和资源消耗。
CMS(Concurrent Mark-Sweep)垃圾回收器是Java虚拟机(JVM)中的一种并发垃圾回收器,它的主要目标是减少垃圾回收对应用线程的影响,以降低应用的停顿时间。CMS回收器的工作过程可以分为以下阶段:
初始标记(Initial Mark):
并发标记(Concurrent Mark):
重新标记(Remark):
并发清除(Concurrent Sweep):
并发重置(Concurrent Reset):
总体来说,CMS垃圾回收器通过并发执行的方式,在标记和清除阶段尽量减少应用的停顿时间。但是,CMS回收器也存在一些缺点,如在标记和清除阶段会产生一些附加的内存开销,可能会导致碎片问题。为了解决这些问题,一些新的垃圾回收器,如G1(Garbage-First)回收器,已经在较新的JVM版本中出现。