一、什么是JDK, JRE, JVM?
JDK: 将java源代码变成java字节码(.class文件)。
JRE: 运行已编译程序所必须的环境,不能将java源代码编译成字节码。
JVM:运行java字节码文件,是执行java程序的虚拟计算机系统,它是 Java 实现跨平台的关键。
Java 程序运行的时候,编译器会将 Java 源代码(.java)编译成操作系统无关的 Java 字节码文件(.class),接下来对应操作系统的 JVM 会对字节码文件进行解释,翻译成对应操作系统的机器指令并运行。
二、JVM 的组织架构
JVM 主要由四大部分组成:类加载器、运行时数据区,执行引擎和本地库接口。下图可以大致描述jvm的结构。
java程序JVM中的执行过程:首先需要编译器编译好的java字节码文件(.class文件),计算机运行时需要通过一定的方法发式(1类加载器)将.class文件加载到内存中(2运行时数据区),但由于字节码文是JVM定义的一套指令集规范,并不能直接交给操作系统去执行,需要特定的命令解释器(3执行引擎)将字节码翻译成特定的操作系统指令集交给cpu去执行,这个过程需要用到一些不同语言为java提供的接口(例如驱动)这就用到了本地Native接口(4本地库接口)
下图展示java程序的运行过程:
当java字节码文件通过通过类加载器加载到内存中时,才能被实例化,然后到JVM中解释执行,最后通过操作系统cpu 执行获取结果。
三、JVM 的内存区域
VM 的内存结构,可以分为程序计数器、虚拟机栈、本地方法栈、堆、方法区等。
- 程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块较小的内存空间。它可以看作是当前线程所执行的字节码行号指示器。
- Java 虚拟机栈就是栈,它的生命周期与线程相同。当线程执行一个方法时,会创建一个对应的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,然后栈帧会被压入栈中。当方法执行完毕后,栈帧会从栈中移除。
- 本地方法栈(Native Method Stacks)与虚拟机栈相似,区别在于虚拟机栈是为 JVM 执行 Java 编写的方法服务的,而本地方法栈是为 Java 调用本地(native)方法服务的,由 C/C++ 编写。在本地方法栈中,主要存放了 native 方法的局部变量、动态链接和方法出口等信息。当一个 Java 程序调用一个 native 方法时,JVM 会切换到本地方法栈来执行这个方法。
- 堆(heap)是 JVM 中最大的一块内存区域,被所有线程共享,在 JVM 启动时创建,主要用来存储对象的。
- 方法区用于存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等。它并不真实存在,属于 Java 虚拟机规范中的一个逻辑概念
四、对象
对象的创建
使用 new 关键字创建一个对象的时候,JVM 首先会检查 new 指令的参数是否能在常量池中定位到一个类的符号引用,然后检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就先执行相应的类加载过程。
如果已经加载,JVM 会为新生对象分配内存,内存分配完成之后,JVM 将分配到的内存空间初始化为零值(成员变量,数值类型是 0,布尔类型是 false,对象类型是 null),接下来设置对象头,对象头里包含了对象是哪个类的实例、对象的哈希码、对象的 GC 分代年龄等信息。
最后,JVM 会执行构造方法(<init>),将成员变量赋值为预期的值,这样一个对象就创建完成了。
对象的访问
所以对象访问方式也是由虚拟机实现而定的,主流的访问方式主要有使用句柄和直接指针两种。
如果使用直接指针访问的话,Java 堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference 中存储的直接就是对象地址,如果只是访问对象本身的话,就不需要多一次间接访问的开销,如图所示:
对象的销毁
当对象创建完成后,就可以通过引用来访问对象的方法和属性,当对象不再被任何引用指向时,对象就会变成垃圾。
垃圾收集器会通过可达性分析算法判断对象是否存活,如果对象不可达,就会被回收。
垃圾收集器会通过标记清除、标记复制、标记整理等算法来回收内存,将对象占用的内存空间释放出来。
五 JVM垃圾回收
JVM提供了多种垃圾回收器,它们使用了不同的算法来管理内存。主要的垃圾回收器包括:
Serial GC:单线程收集器,使用一个GC线程来完成GC工作,且在进行垃圾收集时必须暂停其他所有的工作线程(Stop-The-World),直到它收集结束。适用于单核处理器或小型应用。
Parallel GC:并行收集器,在Serial基础上发展而来,它使用多个GC线程来执行GC工作,以缩短Stop-The-World停顿的时间。适用于多核处理器环境。
CMS(Concurrent Mark Sweep)GC:并发收集器,目标是尽量减少应用的停顿时间。它采用标记-清除算法进行垃圾收集,分为四个阶段:初始标记、并发标记、重新标记、并发清除。
G1(Garbage-First)GC:面向服务端应用的垃圾收集器,是JDK 9以后的默认垃圾收集器。它具备面向局部收集的特点,可以建立可预测的停顿时间模型,同时能够兼顾应用的吞吐量及停顿时间要求。G1收集器将整个Java堆划分为多个大小相等的独立区域(Region),并且能优先处理回收收益最大的区域。
debian-cd-tute
JVM进行垃圾回收的时机通常不是由垃圾回收器主动触发的,而是由JVM根据内存使用情况来决定何时进行垃圾回收。常见的触发条件包括:
内存分配失败:当应用向JVM申请内存,但JVM的堆内存不足以满足申请需求时,JVM会尝试执行垃圾回收来释放内存。
达到阈值:JVM会根据GC日志中设定的阈值来触发垃圾回收,如Eden区(年轻代的一部分)达到一定比例等。
内存溢出和内存泄漏
内存溢出:是指当程序请求分配内存时,由于没有足够的内存空间满足其需求,从而触发的错误。在 Java 中,这种情况会抛出 OutOfMemoryError。
内存泄漏:是指程序在使用完内存后,未能释放已分配的内存空间,导致这部分内存无法再被使用。随着时间的推移,内存泄漏会导致可用内存逐渐减少,最终可能导致内存溢出
总结
学习完jvm,对java程序的运行过程有了更清晰的认识。能清楚的知道jdk,jre,jvm的作用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。