JVM介绍


JVM概念

JVM,即 Java Virtual Machine,Java 虚拟机
JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。

Java的跨平台性

注意:我们提到Java的跨平台性,就会想到JVM,但是能跨平台的是 Java 程序,而不是 JVM。JVM 是用 C/C++ 开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本的 JVM
我们编写的 Java 源码,编译后会生成一种 .class 文件,称为字节码文件。Java 虚拟机(JVM)就是负责将字节码文件翻译成特定平台下的机器码然后运行,也就是说,只要在不同平台上安装对应的 JVM,就可以运行字节码文件,即运行我们编写的 Java 程序。
而这个过程,我们编写的Java 程序没有做任何改变,仅仅是通过 JVM 这一 “中间层” ,就能在不同平台上运行,真正实现了 “一次编译,到处运行” 的目的。
在这里插入图片描述

JRE/JDK/JVM是什么关系

JRE(JavaRuntimeEnvironment,Java运行环境),也就是Java平台。所有的Java 程序都要在JRE下才能运行。普通用户只需要运行已开发好的java程序,安装JRE即可。
JDK(Java Development Kit)是程序开发者用来来编译、调试java程序用的开发工具包。JDK的工具也是Java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是 安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。
JVM(JavaVirtualMachine,Java虚拟机)是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
在这里插入图片描述
在这里插入图片描述
JDK=JRE+多种Java开发工具
JRE=JVM+各种类库

JVM生命周期

启动和消亡:
JVM负责运行一共java程序。当启动一共java程序时,一个虚拟机实例就诞生了。当该程序关闭推出,这个虚拟机实例就随之消失了
JVM运行起点:
java虚拟急实例通过调用某个初始类的main()方法来运行一共java程序。而这个main()方法必须是共有的(public)、静态的(static)、返回值为void,并且接受一个字符串数组作为参数。任何拥有这样一个main()方法的都可以作为Java程序运行的起点。
JVM两种线程:
守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,比如执行垃圾收集任务的线程。
但Java程序也可以把创建的线程标记为守护线程。而Java程序中的初始线程——main()的线程是非守护线程。
只要还有任何非守护线程在运行,那么这个Java程序也在继续运行。当该程序中所有的非守护线程都终止时,虚拟机实例将自动退出。
假若安全管理器允许,程序本身也能够通过调用Runtime类或者System类的exit()方法来退出。

JVM的工作过程

在这里插入图片描述
类加载的子系统: 保证加载正确的类到JVM中
运行时数据区: 类存储及对象及对象运行时变量等存储区域
执行引擎: 将java的字节码交给执行引擎,根据字节码逐个执行

类加载的子系统

java的动态类的装载由装载子系统来实现的,进行加载,连接,在运行第一次引用的类时,进行初始化文件

类加载时机

虚拟机规范中规定有且必须只有5种情况必须对类进行初始化

1、创建对象实例,new对象的时候,会对类进行初始化,前提是类没有被初始化
2、调用类的静态属性或者是类的静态方法
3、通过class文件反射创建对象
4、初始化一个类的子类,使用子类的时候先初始化父类
5、java虚拟机启动时被标记为启动类的类,如:main方法所在的类
注:java类的加载是动态的,并不会一次性加载所有的类到JVM中才执行,保证程序能够正常运行的基础类,其他的类则在需要时才会加载,节约内存开销

不会进行类加载的情况

1、在同一个类加载器下只能初始化类一次,已经初始化的就不会在进行初始化
2、在编译的时候就能确定下来的静态变量,不会对类进行初始化,比如final修饰的静态变量	

类加载器

在这里插入图片描述
Bootstrap ClassLoader:
负责加载 J A V A H O M E 中 j r e / l i b / r t . j a r 里 所 有 的 c l a s s , 由 C + + 实 现 , 不 是 C l a s s L o a d e r 子 类 ∗ ∗ E x t e n s i o n C l a s s L o a d e r : ∗ ∗ 负 责 加 载 j a v a 平 台 中 扩 展 功 能 的 一 些 j a r 包 , 包 括 JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类 **Extension ClassLoader:** 负责加载java平台中扩展功能的一些jar包,包括 JAVAHOMEjre/lib/rt.jarclassC++ClassLoaderExtensionClassLoaderjavajarJAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
App ClassLoader:
负责加载classpath中指定的jar包及目录中class

双亲委派模型

在这里插入图片描述
双亲委派模型的工作过程:
1、当前的类加载器从自己已经加载的类中查询是否此类已经加载,如果已经加载则返回已经加载的类型
2、如果没有找到,就去委托父类加载器去加载,父类加载器采用相同的策略,查看自己已经加载过的类中是否包含这个类,有就返回,没有就委托其父类去加载,直到委托到启动类加载器为止,如果父类加载为空,就从启动类加载器开始进行类的加载
3、如果启动加载器失败,就是使用扩展类加载器来尝试加载,继续失败则会使用Application ClassLoader加载器类加载,继续失败就会抛出一个异常:ClassNotFoundException
使用双亲委派的好处:
1、安全性,避免用户自己编写的类动态替换java的核心类
2、避免类的重复加载,因为JVM判定两个类是否是同一个类,不仅仅根据类名是否相同进行判定,还需要判断加载该类的类加载器是否是同一个类加载器,相同的class文件被不同的类加载器加载得到的结果就是两个不同的类。

类加载的详细过程

加载:查找并加载指定的类的字节码文件
连接:连接包含三块内容:验证、准备、解析

验证:验证加载的class的文件格式、元数据、字节码、符号引用验证
准备:为类的静态的变量分配内存,并初始化默认值   //给变量num分配内存,给定默认值是0
 解析阶段:把类中的符号引用转化为直接引用

初始化:为类的静态变量赋予正确的初始值并且执行静态代码块 //num值给定位5
在这里插入图片描述

运行时数据区域(JMM)

方法区:类级别数据,静态变量存储在这里,线程共享的
堆区:对象及其实例变量和数据存储位置,线程共享
虚拟机栈:线程私有,java程序执行过程中的调用关系,局部信息都会以栈帧形式存储在该位置,线程私有
程序计数器:记录程序下一个执行的位置,线程私有
本地方法栈:保存和OS交互的native方法信息,线程私有

执行引擎

执行存在的字节码信息
提供执行就是来解析字节码,优化字节码,生成中间代码,提供一些组件:垃圾回收、和本地native交互的本地库等等…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值