JVM加载class文件的原理机制实例详解

2023-01-21 0 5,142

目录

一、JVM简介

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

Java语言的一个非常重要的特点就是与平台的 无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改的运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的及其指令执行。这就是Java能够“一次编译,到处运行”的原因。

二、JVM的组成部分

JVM加载class文件的原理机制实例详解

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

JVM加载class文件的原理机制实例详解

1. 类加载器 Class Loader

类加载器的作用是加载类文件到内存,比如编写一个HelloWorld.java程序,然后通过javac编译生成class文件。由Class Loader将class文件加载到内存中。但是Class Loader加载class文件有格式要求。
注意:Class Loader只管加载,只要符合文件结构就加载,至于能不能运行,是由Execution Engine负责。
2. 执行引擎 Exexution Engine
执行引擎也叫作解释器,负责解释命令,提交操作系统执行。
3. 本地接口 Native Interface
本地接口的作用是为了融合不同的编程语言为Java所用。它的初衷是为了融合C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须要有一个聪明的、睿智的调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为native的代码,它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载加载native libraries。目前该方法只有在与硬件有关的应用中才会使用,在企业级应用中已经比较少见,因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等。
4. 运行数据区 Runtime data area
运行数据区使整个JVM的重点。我们所写的程序都被加载到这里,之后才开始运行,Java生态系统如此的繁荣,得益于该区域的优良自治。

三、JVM加载class文件的原理机制

1. Java中的所有类,必须被装载到JVM中才能运行,这个装载工作是由JVM中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,作用就是在运行时加载类。
Java类加载器基于三个机制:委托、可见性和单一性。
(1)委托机制是指加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或加载这个类,那么再加载它。
(2)可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。
(3)单一性原理是指一个类仅被加载一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。
2. Java中的类大致分为三种:
(1)系统类
(2)扩展类
(3)由程序员自定义的类
3. 类装载有两种方式
(1)隐式装载:
程序在运行过程中当碰到通过new等方式生成类或者子类对象、使用类或者子类的静态域时,隐式调用类加载器加载对应的的类到JVM中。
(2)显式装载:
通过调用Class.forName()或者ClassLoader.loadClass(className)等方法,显式加载需要的类。
4. 类加载的动态性体现
一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载再运行,他总是把保证程序运行的基础类一次性加载到JVM中,其他类等到JVM用到的时候再加载,这样是为了节省内存的开销,因为Java最早就是为嵌入式系统而设计的,内存宝贵,而用到时再加载这也是Java动态性的一种体现。
5. Java类加载器
Java中的类加载器实质上也是也是类,功能是把类加载入JVM中,值得注意的是JVM的类加载器有三个,原因有:一方面是为了分工明确,各自负责各自的区块,另一方面为了实现委托模型。
层次结构如下:
BootStrap Loader(引导类加载器) ----- 负责加载系统类

ExtClassLoader(扩展类加载器) ----- 负责加载扩展类
AppClassLoade(应用类加载器)r ----- 负责加载应用类
6. 类加载器之间如何协调工作的
Java中有三个类加载器,碰到一个类需要加载时,Java采用委托模型机制来协调和区分该由哪个类加载器完成。简单来说就是,“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入”,如果Parent找不到,那么才由自己依照自己的搜索路径搜索类。
实例一:

package ClassLoaderTest;
public class ClassLoaderTest {
    public static void main(String[] args) {
        ClassLoader c1 = ClassLoaderTest.class.getClassLoader();
        System.out.println(c1);
        ClassLoader c1Parent = c1.getParent();
        System.out.println(c1Parent);
        ClassLoader c1Root = c1Parent.getParent();
        System.out.println(c1Root);
    }
}

执行结果:

JVM加载class文件的原理机制实例详解

可以看出ClassLoaderTest是由AppClassLoader加载器加载的。AppClassLoader的Parent加载器是ExtClassLoader。但是ExtClassLoader的Parent是null,在Java中是无法获取的。
实例二:

public class Test2 {
    public void test(){
        System.out.println(Test2.class);
        System.out.println(this.getClass());
        System.out.println(Test2.class.getClassLoader());
    }
}
public class Test1 {
    public static void main(String[] args) {
        System.out.println(Test1.class.getClassLoader());
        Test2 test2 = new Test2();
        test2.test();
    }
}

执行结果:

JVM加载class文件的原理机制实例详解

7. 预先加载和依需求加载
Java运行环境为了优化系统,提高程序的执行速度,在JRE运行的开始会将Java运行所需要的基本类采用预先加载(pre-loading)的方法全部加载到内存当中,因为这些单元在Java程序运行的过程当中要经常使用的,主要包括JRE的rt.jar文件里面所有的.class文件。
当java.exe虚拟机开始运行以后,它会找到安装在机器上的JRE环境,然后把控制权交给JRE,JRE的类加载器会自动将lib目录下的rt.jar基础类别文件库加载进内存,这些文件是Java程序执行所必需的,所以系统在开始就将这些文件加载,避免以后的多次IO操作,从而提高程序执行效率。然而我们在程序中需要使用自定义的类的时候就要使用依需求加载(load-on-demand)的方式,就是在Java程序需要用到的时候再加载,以减少内存的消耗。
8. ClassLoader中一些 重要的方法

JVM加载class文件的原理机制实例详解

9.什么地方适用类加载器
最经典的例子就是AppletClassLoader,他被用来加载Applet使用的类,而Applet大部分是在网上使用,而非本地的操作系统使用。使用不同的类加载器,你可以从不同的源地址加载同一个类,它们被视为不同的类。J2EE使用多个类加载器加载不同地方的类,例如War文件由Web-app类加载器加载,而EJB-JAR中的类由另外的类加载器加载。有些服务器也支持热部署,这是由类加载器实现。你也可以使用类加载器来加载数据库或者其他持久层的数据。
10. 类加载器的阶层体系
Java类加载器的工作原理:
当执行Java的.class文件的时候,java.exe会帮助我们找到jRE,接着找到JRE内部的jcm.dll,这才是真正的Java虚拟机器,最后加载动态库,激活Java虚拟机器。虚拟机激活以后,会先做一些初始化的动作,比如说读取系统参数等。一旦初始化动作完成后,就会产生第一个类加载器-----Bootstrap Loader,Bootstrap Loader是由C++撰写而成,这个Bootstrap所做的初始工作中,除了一些基本的初始化动作之外,最重要的就是加载Launcher.java之中的ExtClassLoader,并设定其parent为null,代表其父加载器为BootstrapLoader。然后Bootstrap loader再要求加载Launcher.java之中的AppClassLoader,并设定其parent为之前产生的ExtClassLoader实体。这两个类加载器都是以静态类的形式存在的。注意:Launcher E x t C l a s s L o a d e r . c l a s s 与 L a u n c h e r ExtClassLoader.class与Launcher ExtClassLoader.class与LauncherAppClassLoader.class都是由Bootstrap Loader所加载,所以Parent和由哪个类加载器加载没有关系。
三者之间的关系:
Bootstrap Loader <—(extends)-----ExtClassLoader <—(extends)—AppClassLoader
这三个类加载器构成了Java的类加载体系。它们分别从以下的路径寻找程序所需要的类:
Bootstrap Loader:sun.boot.class.path
ExtClassLoader:java.ext.dirs
AppClassLoader:java.class.path
这三个参数可以通过System.getProperty()函数得到具体对应的路径。

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 JVM加载class文件的原理机制实例详解 http://www.20zxx.cn/463564/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务