美文网首页
[JVM] 类加载机制

[JVM] 类加载机制

作者: Colors_boy | 来源:发表于2020-11-16 12:30 被阅读0次

JVM,Java虚拟机,负责Java源代码的识别与执行。

1. 类加载过程

任何程序需要加载到内存才能与CPU进行交流,字节码.class文件同样需要加载到内存,才能实例化类。

首先,通过类加载器classLoader提前将.class文件加载到内存中,使用的是“双亲委派加载模型”。

类加载的过程主要为以下三步:加载、连接、初始化

  1. 第一步, Load阶段读取类文件产生二进制流,并转化为特定的数据结构,初步校验cafe babe 魔法数、常量池、文件长度、是否有父类等,然后创建对应类的 java.Jang.Class实例。
  2. 第二步,Link阶段包括验证、准备、解析三个步骤。验证是更详细的校验,比如final是否合规、类型是否正确、静态变量是否合理等准备阶段是为静态变量分配内存,并设定默认值,解析类和方法确保类与类之间的相互引用正确性,完成内存结构布局。
  3. 第三步,Init阶段执行类构造器<clinit>方法,如果赋值运算是通过其他类的静态方法来完成的,那么会马上解析另外一个类,在虚拟机栈中执行完毕后通过返回值进行赋值。
图1.png

类加载是一个将 class 字节码文件实例化成Class对象并进行相关初始化的过程。在这个过程中,JVM会初始化继承树上还没有被初始化过的所有父类,并且会执行这个链路上所有未执行过的静态代码块、静态变量赋值语旬等。某些类在使用时,也可以按需由类加载器进行加载。

2. 类加载器的划分

启动类加载器(Bootstrap ClassLoader):负载装载最核心的Java类,如Object、String等。

扩展类加载器(Extendsion ClassLoader): 加载一些扩展的系统类,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。

应用程序类加载器( Application ClassLoader ): 主要加载用户定义的 CLASSPATH 路径下的类。


3. 类加载器的双亲委派模型

低层次的当前类加载器,不能覆盖更高层次类加载器已经加载的类。如果低层次的类加载器想加载一个未知类,要非常礼貌地向上逐级询问:“ 请问,这个类已经加载了吗?被询问的高层次类加载器会自问两个问题,第一,我是否已加载过此类,第二,如果没有,是否可以加载此类?只有当所有高层次类加载器在两个问题上的答案均为“否”时,才可以让当前类加载器加载这个未知类。逐级询问是否已加载此类,直至BootstrapClassLoader,然后向下逐级尝试是否能够加载此类,如果都加载不了,则通知发起加载请求的当前类加载器;准予加载。在右侧的三个小标签里,列举了此层类加载器主要加载的代表性类库事实上不止于此。

图2.png

需要自定义类加载器的几种情况:

  • 隔离加载类:在某些框架内进行中间件与应用的模块隔离,把类加载到不同的环境。
  • 修改类加载方式:类的加载模型并非强制,除了Bootstrap外,其他的加载并非一定要引入,或者根据实际情况在某个时间段进行按需进行加载。
  • 扩展加载源:比如从数据库、网络进行加载。
  • 防止源码泄露:Java代码容易被编译和纂改,可以进行编译加密。那么类加载器也需要自定义,还原加密的字节码。

4.实现自定义类加载器

继承ClassLoader,重写findclass()方法,调用define()方法。

public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] result = getClassFromCustomPath(name);
            if (result == null) {
                throw new FileNotFoundException();
            } else {
                return defineClass(name, result, 0, result.length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new ClassNotFoundException(name);
    }

    private byte[] getClassFromCustomPath(String name) {
        //从自定义路径中加载类
        return null;
    }

    public static void main(String[] args) {
        CustomClassLoader customClassLoader = new CustomClassLoader();
        try {
            Class<?> clazz = Class.forName("one", true, customClassLoader);
            Object obj = clazz.newInstance();
            System.out.println(obj.getClass().getClassLoader());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

由于中间件一般都有自己的依赖 jar 包,在同 个工程内引用多个框架时 往往
被迫进行类的仲裁。按某种规则 jar包的版本被统一指定,导致某些类存在包路径、
类名相同的情况就会引起类冲突 ,导致应用程序出现异常。主流的容器类框架都会
自定义类加载器,实现不同中间件之间的类隔离 有效避免了类冲突。

注明:笔记大部分采自书本《码出高效》

相关文章

  • JVM——类加载机制

    前言 今天就来介绍类的加载机制以及双亲委派机制。 JVM 类加载机制 JVM 类加载的五个阶段 JVM 类加载机制...

  • JVM类加载学习二-类加载机制学习

    JVM类加载机制 @(Java)[JVM|类文件结构] [TOC] 基本介绍 JVM的类加载机制:JVM把描述类的...

  • JVM——类加载机制

    JVM类加载机制 JVM类加载机制是通过类加载器ClassLoader来将.class文件加载到内存中,以便调用....

  • 类加载机制(一)

    加载机制系列类加载机制(一)类加载机制(二)类加载机制(三) 类加载机制 1.JVM把class文件加载到内存,对...

  • java类加载机制、类加载器、自定义类加载器

    java类加载机制、类加载器、自定义类加载器 类加载机制 java类从被加载到JVM到卸载出JVM,整个生命周期包...

  • Java——JVM篇——收藏系列来啦(终结篇)

    转自:Java——JVM篇——收藏系列来啦(终结篇)侵删。 2.9.JVM 类加载机制 JVM 类加载机制分为五个...

  • 类加载机制

    类加载机制 类加载机制是指 .class文件加载到JVM,并形成Class对象的机制。 类加载机制可以在运行时动态...

  • JVM类加载机制

    这节主要从覆盖JDK的类开始学习JVM的类加载机制。Java和JVM的类加载机制类似,但JVM的类加过程稍有些复杂...

  • 2020最新JAVA核心面试知识整理283页(带详解)

    部分目录预览 部分内容预览 JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下...

  • JAVA类加载机制

    jvm之java类加载机制和类加载器(ClassLoader)的详解java类加载机制:全盘负责、双亲委派、缓存机...

网友评论

      本文标题:[JVM] 类加载机制

      本文链接:https://www.haomeiwen.com/subject/xswabktx.html