详解JVM
JVM(Java Virtual Machine)是Java虚拟机的缩写,它是一个虚构出来的计算机,充当着Java代码与底层操作系统之间的桥梁。
JVM、JRE和JDK的关系
- JDK (Java Development Kit): Java开发工具包,提供了编译、调试Java程序所需的工具,是面向开发者的。它包含了JRE。
4 - JRE (Java Runtime Environment): Java运行环境,包含了JVM和Java程序运行所需的核心类库,是运行Java程序所必需的。
4 - JVM (Java Virtual Machine): Java虚拟机,是JRE的一部分,负责执行Java字节码。
4
JVM内存结构
JVM在运行时会将其管理的内存划分为若干个不同的数据区域,主要包括以下几个部分:
- 程序计数器 (Program Counter Register): 一块较小的内存空间,用于记录当前线程所执行的字节码的行号指示器。
4 - Java虚拟机栈 (Java Virtual Machine Stacks): 线程私有,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
1 - 本地方法栈 (Native Method Stacks): 与虚拟机栈类似,但为虚拟机使用到的Native方法服务。
1 - Java堆 (Heap): JVM所管理的内存中最大的一块,被所有线程共享,用于存放对象实例和数组。
2 - 方法区 (Method Area): 线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
2
类加载机制
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的过程。
- 加载 (Loading): 通过一个类的全限定名来获取定义此类的二进制字节流。
2 - 验证 (Verification): 确保Class文件的字节流中包含的信息符合当前虚拟机的要求。
2 - 准备 (Preparation): 为类变量分配内存并设置类变量初始值的阶段。
2 - 解析 (Resolution): 虚拟机将常量池内的符号引用替换为直接引用的过程。
1 - 初始化 (Initialization): 执行类构造器
<clinit>()方法的过程。1
双亲委派模型
当一个类加载器收到类加载请求时,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
垃圾回收 (Garbage Collection)
Java的一个重要特性就是通过垃圾收集器(Garbage Collector, GC)自动管理内存,回收不再使用的对象。
如何判断对象已死?
- 引用计数法: 给对象中添加一个引用计数器,但很难解决对象之间相互循环引用的问题。
3 - 可达性分析算法: 通过一系列的名为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
3
- 引用计数法: 给对象中添加一个引用计数器,但很难解决对象之间相互循环引用的问题。
常见的垃圾回收算法
- 标记-清除 (Mark-Sweep): 分为“标记”和“清除”两个阶段,但会产生大量不连续的内存碎片。
1 - 复制 (Copying): 将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面。
1 - 标记-整理 (Mark-Compact): 标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
1 - 分代收集 (Generational Collection): 根据对象存活周期的不同将内存划分为几块,一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
1
- 标记-清除 (Mark-Sweep): 分为“标记”和“清除”两个阶段,但会产生大量不连续的内存碎片。
常用JVM工具
JDK提供了一些小工具,用于监控和排查JVM相关问题。
- jps: 列出正在运行的虚拟机进程。
1 - jstat: 用于监视虚拟机各种运行状态信息的命令行工具。
1 - jmap: 用于生成堆转储快照。
1 - jstack: 用于生成虚拟机当前时刻的线程快照。
1