JVM详解

什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具

体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

Java为什么是"平台无关的编程语言"

Java虚拟机是一个可以执行Java字节码的虚拟机进程。

Java源文件被编译成能被Java虚拟机执行的字节码文件(.class文件)。

Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。

Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

JRE/JDK/JVM是什么关系

JRE是Java运行环境,即(Java Runtime Environment),也就是Java平台。所有的Java程序都要在JRE下才能运行。

JDK是开发工具包,即(Java Development Kit),它是程序开发者用来编译、调试Java程序,它也是Java

程序,也需要JRE才能运行。

JVM是Java虚拟机,即(Java Virual Machine),它是JRE的一部分,一个虚构出来的计算机,它支持跨平台。

小结

Java虚拟机成为jvm,它是分离了一部分真实电脑的资源。我们写的Java程序都是在JVM上运行的,不是在真实的计算机上运行。

程序员写程序 -> JVM ->真实的计算机。

JVM解决了各操作系统兼容性问题。

目前最新版本是jdk22,使用版本一般是JDK8,JDK只有3个版本是商用免费的,即8、11、17。

JDK:开发和运行 ,其中包含了JRE,可以将.java文件 字节 为.class文件。

JRE:运行环境,其中包含JVM,运行.class文件。

JVM:通过运行.class文件去调用底层操作系统。
三种JVM :

① Sun公司的HotSpot;

② BEA公司的JRockit;

③ IBM公司的J9 JVM;

在JDK1.7及其以前我们所使用的都是Sun公司的HotSpot,但由于Sun公司和BEA公司都被oracle收购,

jdk1.8将采用Sun公司的HotSpot和BEA公司的JRockit两个JVM中精华形成jdk1.8的JVM。

JVM原理

JVM是Java核心和基础,在Java编译器和os平台之间的虚拟处理器,可以在上面执行Java的字节码程序。Java编译器主要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台的机器码,通过特定平台运行。

JVM体系结构

类加载器:加载class文件。

执行引擎:执行字节码或者执行本地方法。

运行时数据区:包括方法区、堆、Java栈、PC寄存器、本地方法栈。

JVM运行时数据区

1.类加载器(ClassLoader):在JVM启动时或者在类运行时将需要的class加载到JVM中。

2.执行引擎:负责执行class文件中包含的字节码指令

3.内存区(也叫运行时数据区)是在JVM运行的时候操作所分配的内存区。

运行时内存区主要可以划分为6个区域:
PC寄存器 :用于存储每个线程下一步将执行的JVM指令。
:栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放当前线程中的局部基本类型的变量。
:是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。堆是JVM所有线程共享的。
方法区 :存放了所加载的类信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息;通过class对象中的getName等方法来获取信息时,实际这些数据是来源于方法区,方法区是全局共享的。
运行时常量池 :存放类中固定的常量信息、方法和Field的引用信息等,其空间是从方法区中分配。
本地方法栈 :JVM采用本地方法栈来支持native方法的执行,此区域用于存储每个native方法调用的状

态。

加载顺序


方法区(Method Area) :用于存储类结构信息的地方,包括常量池、静态变量、构造函数等。虽然JVM规范把方法区描述为堆的一个逻辑部分, 但它却有个别名non-heap(非堆)。方法区还包含一个运行时常量池。
java堆(Heap) :存储java实例或者对象的地方。这块是GC的主要区域(GC具体相关请查看之前的文章)。从存储的内容可以很容易知道,方法区和堆是被所有java线程共享的
java栈(Stack) :java栈总是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的java栈。在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作

栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。所以java栈是线程私有的
程序计数器(PC Register) :用于保存当前线程执行的内存地址。由于JVM程序是多线程执行的(线程轮流切换),所以为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的
本地方法栈(Native Method Stack) :和java栈的作用差不多,只不过是为JVM使用到的native方法服务的。
本地方法接口 :主要是调用C或C++实现的本地方法及返回结果。

扩展一个小知识:

如何判断对象是否存活

引用计数法 :给对象中添加一个引用计数器,当一个地方引用了对象,计数加1;当引用失效,计数器减

1;当计数器为0表示该对象已死、可回收;但很难解决循环引用问题;
可达性分析 :通过一系列称为"GC Root"的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径

称为引用链 ,当一个对象GC Roots没有任何引用链相连,则证明此对象已死、可回收。

Java中可以作为GC Roots的对象包括:
虚拟机栈中引用的对象、本地方法栈中native方法引用的对象、方法区静态属性引用的对象、方法区常量引用的对象

总结

线程共享:方法区、堆

线程私有:java栈、本地方法栈、程序计数器

①堆空间(Heap):

存放创建出来的对象、对象中的属性,是共享的。

是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建。线程共享,此内存区域的唯一目的就是存放

对象实例。

②方法区(Method Area):

存放方法、常量、静态变量、构造函数、字符串常量池,是共享的。

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

③栈区(JVM Stacks):

存放局部变量、方法的调用过程(栈帧)、方法的返回值,栈中的数据会随着栈的使用结束而销毁,是线程私有,生命周期与线程相同。

虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)

用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

④程序计数器(Program Counter Register):

多线程切换执行时,保证每个线程都能正常切换。

线程私有,是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。

⑤本地方法区(Native Method Stacks):

线程私有,与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。

注: Native Method就是一个java调用非java代码的接口。

相关推荐
2401_85439108几秒前
高效开发:SpringBoot网上租赁系统实现细节
java·spring boot·后端
Cikiss9 分钟前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
wxin_VXbishe10 分钟前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php
Cikiss10 分钟前
微服务实战——平台属性
java·数据库·后端·微服务
无敌の星仔19 分钟前
一个月学会Java 第2天 认识类与对象
java·开发语言
OEC小胖胖24 分钟前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
2401_857617621 小时前
SpringBoot校园资料平台:开发与部署指南
java·spring boot·后端
quokka561 小时前
Springboot 整合 logback 日志框架
java·spring boot·logback
计算机学姐1 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
救救孩子把1 小时前
深入理解 Java 对象的内存布局
java