Java JVM原理与常识知识点
Java虚拟机(Java Virtual Machine,JVM)是Java语言实现跨平台的核心部件。它是一个用来执行Java字节码的虚拟机,Java源文件被编译成能够运行在JVM上的字节码文件。因此,深入了解JVM的原理是Java编程中必不可少的一部分。
本文将从以下几个方面进行讲解Java JVM原理与常识知识点:
- JVM定义和架构
- JVM内存模型
- 垃圾回收机制
- 类的加载和Java类的卸载
JVM定义和架构
JVM是运行Java字节码的虚拟机。它是Java语言的核心部分,Java应用程序运行在JVM上,JVM负责为程序提供跨平台能力和自动内存管理机制。
JVM的架构分为三个部分:类加载器、运行时数据区和执行引擎。Java应用程序在JVM上最终会被翻译成本地机器码,由执行引擎去执行。
以Tomcat服务器的启动为例,我们可以看到JVM启动的流程:
$ sh catalina.sh start
- 系统通过catalina.sh这个脚本找到JRE路径,然后启动JVM
- JVM启动后,会执行bootstrap classloader,该classloader会加载Java核心类库
- JVM接着执行扩展classloader,该classloader会加载扩展的Java类库
- 最后,执行应用程序classloader,该classloader会加载应用程序的Java类库
JVM内存模型
JVM内存模型分为三个部分:程序计数器、Java虚拟机栈和堆。分别是线程私有的、线程私有的和线程共享的。堆内存承载了大部分Java对象的实例,是垃圾收集和对象分配的主要区域。
Java虚拟机栈储存线程的局部变量、部分结果和返回值,会跟着方法的调用和返回进行入栈和出栈操作。当线程执行完该方法之后,该栈帧被弹出,栈内变量的空间被回收。
程序计数器(PC寄存器)是线程私有的,一直记录着当前线程执行的字节码地址。每个线程独立拥有各自的程序计数器,防止多线程之间的执行互相干扰。
垃圾回收机制
Java是一门自动内存管理的语言,因此Java内存的管理是由JVM完成的。在JVM的内存模型中,堆是最主要的一块内存。垃圾回收机制是Java保证自动内存回收和内存分配效率的核心,垃圾回收器是JVM中实现垃圾回收的组件。
Java的垃圾回收机制通过检测和回收属于不再使用的对象内存来提高性能和减少Bug。
Java垃圾收集机制的工作原理基于可达性分析算法,判断哪些对象不再被程序使用。这个算法的主要思想是从根节点开始,向下搜索所有正在被使用的对象,未被搜索到的对象即为不可达的垃圾对象,被回收器标记并回收内存空间。
JVM自带了多种垃圾回收器,不同的垃圾回收器适合不同的场景。例如:
Serial垃圾回收器适合单线程在小堆上的场景;
Parallel垃圾回收器适合多核CPU和大堆场景;
CMS垃圾回收器适合低延迟的场景;
G1收集器适合多核CPU、大堆和高吞吐量应用程序的场景。
类的加载和Java类的卸载
Java应用程序在运行时会被加载到JVM的内存中。类的加载包括三个过程:加载、链接和初始化。
- 类加载:当Java程序需要使用一个类时,JVM首先会检查该类是否已经被加载,如未加载,JVM就会通过类加载器将相关的类文件加载到内存中。
- 链接:类的链接又分为三个过程:验证、准备和解析。“验证”确保加载的类符合Java语言的语法规范和字节码的正确性;“准备”是为类中的静态变量分配内存并设置默认初始值;“解析”是将类、接口、字段和方法的符号引用转换为直接引用。
- 初始化:当类加载和链接都完成后,JVM就会对该类进行初始化。类的初始化是可选的,它提供了一个机会去执行静态初始化和初始化字段。
Java类的卸载是一个相对较新的技术,只有在JVM对新类定义的存在确认没用后才会触发。JVM定义了一个称为类卸载的处理机制唤醒并所有被卸载的类的finalize()方法。这个方法通常用于关闭时释放和清理资源,类第一次被垃圾回收时,会自动调用finalize()方法进行善后处理。
示例说明
-
使用VisualVM来监控Tomcat的堆内存使用。VisualVM是JDK自带的工具之一。可以通过它查看JVM的系统属性、内存信息、线程堆栈、垃圾回收、传统视图,还可以进行内存分析、线程分析和Java应用程序的性能测试。
VisualVM Monitoring Tomcat Heap Memory Usage -
Java垃圾回收的示例:
public class Foo {
private static final int ARRAY_SIZE = 1024 * 1024;
private static final int ARRAY_COUNT = 128;
public static void main(String[] args) {
byte[][] arrays = new byte[ARRAY_COUNT][];
for (int i = 0; i < ARRAY_COUNT; ++i) {
arrays[i] = new byte[ARRAY_SIZE];
}
System.out.println("Created " + ARRAY_COUNT + " arrays of size " + ARRAY_SIZE);
// 系统垃圾回收
System.gc();
System.out.println("GC done");
}
}
该示例创建了大量的字节数组,然后在执行GC操作之后观察对象内存是否被回收。执行这个程序后可以使用JVisualVM工具进行内存分析,比较垃圾回收前后内存分配与使用情况的差异。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java JVM原理与常识知识点 - Python技术站