JVM介绍和类加载机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014803081/article/details/88893406

JVM

什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

JVM原理

JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。
在这里插入图片描述
java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。

执行过程:

  1. 加载.class文件 2) 管理并分配内存 3) 执行垃圾收集
    JRE(java运行时环境)由JVM构造的java程序的运行环,也是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间。JVM在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机。操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境:1) 创建JVM装载环境和配置 2) 装载JVM.dll 3) 初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例4) 调用JNIEnv实例装载并处理class类。

生命周期

  1. JVM实例对应了一个独立运行的java程序它是进程级别
    a) 启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点
    b) 运行。main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,java程序也可以表明自己创建的线程是守护线程
    c) 消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出
  2. JVM执行引擎实例则对应了属于用户运行程序的线程它是线程级别的
    5、体系结构
    在这里插入图片描述
    类装载器(ClassLoader)(用来装载.class文件)
    执行引擎(执行字节码,或者执行本地方法)
    运行时数据区(方法区、堆、java栈、PC寄存器、本地方法栈)

类加载器

类型

我们首先看一下JVM预定义的三种类型类加载器,当一个 JVM启动的时候,Java缺省开始使用如下三种类型类装入器:
a.启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
b.扩展(Extension)类加载器:扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher E x t C l a s s L o a d e r &lt; J a v a R u n t i m e H o m e &gt; / l i b / e x t D j a v a . e x t . d i r 使 c . S y s t e m S u n A p p C l a s s L o a d e r s u n . m i s c . L a u n c h e r ExtClassLoader)实现的。它负责将&lt; Java_Runtime_Home &gt;/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。 c.系统(System)类加载器:系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。
d.除了以上列举的三种类加载器,还有一种比较特殊的类型就是线程上下文类加载器。
在这里插入图片描述
我们可以看出,类加载器均是继承自java.lang.ClassLoader抽象类。
父子关系图
在这里插入图片描述

工作原理

类加载器的工作原理基于三个机制:委托、可见性和单一性。
a.可见性:根据可见性原则,子级类加载器可以看到父级类加载器加载的类文件,但是反过来则行不通。这意味着,假如Application类加载器加载了Abc.class 文件,那么尝试使用Extension类加载器去加载Abc.class 文件,则会抛出异常java.lang.ClassNotFoundException。
b.委托:在探讨java中的类文件在什么时候被加载和初始化的问题时,java中的类文件在它被需要的时候被加载。假设您有一个叫做Abc.class 的应用程序特定的类文件,加载这个类文件的第一个请求发送到 Application类加载器。Application类加载器委托它的父级Extension类加载器,而Extension类加载器委托给Bootstrap类加载器。Bootstrap类加载器在rt.jar 中寻找类文件,由于没有找到,请求转发到Extension类加载器。Extension类加载器在jre/lib/ext目录中寻找类文件并尝试加载类文件,如果找到了类文件,这时Extension类加载器将会加载类文件(Application类加载器将永远不会加载类文件);但是如果Extension类加载器没有加载类文件,那么Application类加载器将会从java类路径中加载类文件。请注意:类路径用于加载类文件,而路径用来查找可执行的像javac or java 的命令。
c.单一性: 根据这个原则,一个类文件被父级类加载器加载后,子级类加载器则不能加载它。尽管完全可以编写一个类加载器,它自己加载类文件,这违反了委托和唯一性原则,这样做没有什么好处。在您编写您自己的类加载器时,您应当遵守所有的类加载器原则。

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的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。

猜你喜欢

转载自blog.csdn.net/u014803081/article/details/88893406