JVM虚拟机

JVM

1、 JVM 概述

🚴 🚴 🚲 🚴‍♀

虚拟机(Virtual Machine)是一台虚拟的计算机。VMware属于系统虚拟机,是对物理计算机的仿真。Java虚拟机是程序虚拟机,为专门执行某个单个计算机程序而设计,在Java中执行的指令我们称为Java字节指令码。

jvm作用:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cw4ohv9C-1662022893347)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364622620.png)]

Java虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台上的机器码指令执行。

特点:一次编译,自动内存管理,自动垃圾回收功能。

JVM四个组成部分

1、类加载器系统(Class Loader):负责从硬盘上加载字节码文件。

2、运行时数据区(Runtime Data Area):存储运行时数据,包含方法区,堆,栈,本地方法栈,程序计数器。

3、执行引擎(Execution Engine):负责将字节码解释/编译为真正的机器码。

4、本地方法接口(Native Interface):负责调用操作系统本地方法。

我们常说的JVM组成指的是运行时数据区里面的Heap(堆)模块。

简图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PI44aT7K-1662022893348)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364739275.png)]

详细图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOKeZLb4-1662022893348)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364761999.png)]

jvm位置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jkW4mvKA-1662022893349)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364675882.png)]

JVM 是运行在操作系统之上的,它与硬件没有直接的交互。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7raX2GiX-1662022893349)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364699992.png)]

2、类加载系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-udHbkBZC-1662022893349)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660364892595.png)]

类加载子系统

字节码文件存储在硬盘中,运行时,由类加载系统将类的信息加载在到内存中(方法区)。

类加载角色

class file存在于硬盘中,是一个模板,加载到JVM中,被称为DNA元数据模板,存放在方法区。类加载子系统负责将文件从文件系统或者网络中加载class文件,class->JVM->元数据模板,使用的是ClassLoader进行加载,充当一个快递员的角色。

类加载过程

1、加载(Loading)

将硬盘字节码读入到内存中,生成此类的Class对象,把硬盘上的结构转为内存结构。

2、链接(Linking)

第一,验证(Verification)

​ 验证字节码格式,是否被修改或者污染。

​ 验证语法,例如类是否继承final的类。

第二,准备(Preparation)

​ 在准备阶段为类中静态的变量赋予初始值,并设置默认初始值。不包含用final修饰的static常量,在编译时进行初始化。例如:public static int value = 123; value在准备阶段后的初始值不是123,是0.

第三,解析(Resolution)

​ 将类的二进制数据中的符号引用替换成直接引用,符号引用是Class文件的逻辑符号,直接引用是指向方法区中的实际地址。

3、初始化(Initialization)

什么时候初始化?

​ 1、new一个对象,创建类的实例

​ 2、访问某个类或接口的静态变量或者对该静态变量赋值

​ 3、调用类的静态方法

​ 4、反射,Class.forName(" ")

​ 5、初始化一个类的子类,先会初始化子类的父类

类的初始化顺序

对static修饰的变量或语句进行赋值。如果包含多个静态变量和静态代码块,按照自上而下顺序依次执行。如果初始化一个类的时候父类未初始化,则先初始化父类。

父类static->子类static->父类构造方法->子类构造方法。

类加载器分类

类加载器是负责加载类的类。

从JVM的角度上分为:

1、启动类加载器(引导类加载器),这部分不是用Java写的。

2、其他类加载器。这部分只用Java写的类加载器。

从程序员角度分为:

1、启动类加载器(Bootstrap ClassLoader),负责加载Java核心类,即扩展类加载器和应用程序类加载器,并未他们指定父类加载器。使用C/C++实现,嵌套在JVM内部。考虑安全,所以启动类加载器存放在<JAVA_HOME>\lib目录,或者被-Xbootclasspath参数锁指定路径中存储放的类。

2、扩展类加载器(Extension ClassLoader),由sun.misc.Launcher$ExtClassLoader实现。负责加载\jre\lib\ext目录下的类,包含应用程序类加载器。派生于ClassLoader类。

3、应用程序类加载器/系统类加载器(Application ClassLoader),由sun.misc.Launcher$AppClassLoader实现。负责加载自己写的程序中的类。该类加载器是程序中默认的类加载器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ihw4hkV-1662022893350)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1655884153778.png)]

ClassLoader类是一个抽象类,其后所有的类加载器都继承于ClassLoader(不包括启动类加载器)。

双亲委派机制

按需加载,保证类加载的正确性,安全性,采用双亲委派机制。

作用:保证JDK的核心类优先加载。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fnQSqlGS-1662022893350)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1655884963846.png)]

原理:当需要加载程序中的一个类的时候,会先让父级去加载,直到最顶级的类加载器,如果父级找到了则返回使用,如果没有找到,则委托给子级去加载,找到了就返回。如果所有的类加载器没有找到,则报ClassNotFoundException类找不到异常。

优点:安全,避免自己写的类替换系统中的类,避免类重复加载。

为什么要打破双亲委派机制?

举个例子:数据库驱动Driver接口,Driver定义在JDK中,当其实现却是各个数据库服务商,例如mysql的MYSQL CONNECROR就有这个问题,DriverManger要加载各个Driver接口实现类进行管理,但是DriverManager是由启动类加载器进行加载的,而启动类加载器默认加载JAVA_HOME下面的lib目录,但我们真正要加载的是各个实现类,需要由系统类加载器进行加载,这个时候就需要启动类加载器委托系统类加载器区加载Driver实现类,从而破坏双亲委派机制。

如何打破双亲委派机制?

1、Java中提供了一个ClassLoader类,定义哪些方法加载类。重写loadClass方法,这个方法可以指定类通过什么类加载器来进行加载,如果改写他的规则,则相当于打破了双亲委派机制。loadClass(String classpath);//建议使用,底层使用双亲委派机制加载类。

findClass(String classpath);//如果需要自定义,可以重写findClass()。

defineClass()将读到class文件的数据,构造出一个Class对象。

2、使用线程上下文类

引入线程上下类加载器,通过java.lang.Thread类的setContextClassLoader()方法进行设置。如果创建线程是还未设置的,它会从父类线程继承一个;如果在应用程序全局范围内没有设置,那么这个线程上下类加载器就是应用程序类加载器。那么这样JNDI服务使用这个线程上下类加载器去加载所需的spi代码,也就是父类加载器请求子类加载器去完成类加载的动作,这个实际是打通了双亲委派的逆向层次结构。

类的主动使用/被动使用

主动使用,会加载初始化。

1、new对象;2、使用类的静态成员(静态变量、静态方法);3、反射动态加载类Class.forName();4、子类被加载;5、执行main函数。

被动使用,不会加载初始化。

1、访问类中的静态常量;

public final static int NUMBER = 5 ; //不会导致类初始化,被动使用 。

public final static int RANDOM = new Random().nextInt() ; //会导致类的初始化,主动使用 。

2、将类作为类型,例如创建数组,用类作为类型使用。

Student[] students = new Student[10] ;

3、运行时数据区

运行时数据区组成

1、程序计数器:是一块较小的空间,是当前线程所执行的字节码的行号指示器

2、Java虚拟机栈:描述的是Java方法执行的内存模型,每个方法在执行的同时会创建一个线帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程都对应着一个线桢在虚拟机栈中入栈出栈的过程。

3、本地方法栈:与虚拟机栈一样,虚拟机栈是服务Java方法的,本地方法栈是为虚拟机调用native方法服务的。

4、Java堆:是Java虚拟机中内存最大的一块,是被所有线程共享的,在虚拟机启动时候创建,Java堆唯一的目的就是存放对象实例,机会所有对象实例都在这里分配内存。

5、方法区:储存已被虚拟机加载的类信息、常量、静态资源、即时编译后的代码等数据。方法区是很重要的系统资源,是硬盘和CPU的中间桥梁,承载着操作系统和应用程序的实时运行。

jvm内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了jvm的高效稳定运行,不同的jvm对于内存的划分方式和管理机制存在着部分差异。下面是最流行的HotSpot虚拟机。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CiFK1yfS-1662022893350)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660380587912.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qp0PjyBE-1662022893351)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660380653982.png)]

程序计数器(Program Counter Register)

程序计数器用来存储下一条指令的地址和将要执行的指令代码,由执行引擎读取下一条指令。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZQRrOx2w-1662022893351)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660621361086.png)]

每个线程都有自己的程序计数器,是线程私有,生命周期与线程生命周期保持一致。

任何时间一个线程里只有一个方法执行,程序计数器会存储当前线程正在执行的Java方法的JVM指令地址。

程序计数器是程序控制流的指示器,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。

字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

程序计数器是唯一一个在Java虚拟机规范中没有任何规定任何OutOfMemoryError的情况的区域。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QpL6310w-1662022893351)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1660703882321.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值