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

JVM类加载机制

作者: 黄靠谱 | 来源:发表于2019-02-12 16:45 被阅读8次

概述

class物理文件加载到JVM内存中,可以有多种加载方式:

  • 3种JDK自带的ClassLoader.
  • 自定义的ClassLoader(重写ClassLoader)
  • 反射、JDK动态代理、CGLIB也可以实现运行期编译生成一个新的java对象

类的加载器和核心类

  1. 核心类加载器
  • BootstrapClassLoader 最顶层的加载类,负责加载lib下的rt.jar、resources.jar、charsets.jar和class等
  • ExtentionClassLoader 加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件
  • AppClassLoader 加载当前应用的classpath的所有类
  • 自定义ClassLoader,可以突破class文件包路径的限制,可以修改类加载机制(比如热加载),需要重写findClass()缓存查找方法制定寻找路径即可
  1. 加载的特点
  • 不同包路径下的类由不同的类加载器加载
  • jvm懒加载,根据需要去动态加载
  • 父加载器不是父类,双亲委托:自下而上,先挨个找缓存,到了顶层缓存中还没有,就开始初始化,从各自对应负责的包路径下查找,有就创建,没有给就子加载器加载
  • 加载之后存在缓存当中
  1. 加载的结果
  • 将class文件加载在内存中。
  • 将静态数据结构(数据存在于class文件的结构)转化成方法区中运行时的数据结构(数据存在于JVM时的数据结构)。
  • 在堆中生成一个代表这个类的java.lang.Class对象,作为数据访问的入口。
  1. 核心方法: loadClass、 findLoadedClass、parent.loadClass、findBootStrapClass、findClass

自定义类加载器

实现自定义class文件加载路径,实现,class文件包路径的限制

https://www.cnblogs.com/gdpuzxs/p/7044963.html

实现逻辑:写一个classloader类(构造函数里面需要传入包真实的路径),重写findClass方法,

public class MyClassLoader extends ClassLoader{
    public MyClassLoader(String classpath) {
        this.classpath = classpath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte [] classDate=getDate(name);
            
            if(classDate==null){}
            
            else{
                return defineClass(name,classDate,0,classDate.length);
            }
            
        } catch (IOException e) {
            
            e.printStackTrace();
        }
        
        return super.findClass(name);
    }
}

实现类的每次重新加载,实现热加载

  1. 本来重写 findLoadedClass()即可,直接返回null,实现热加载,但是ClassLoader把该方法设置为final了,不希望去破坏这个规则
  2. 所以直接通过重写过的findClass来实现,相当于在上面的基础上做修改,findClass的路径为当前路径,每次loadClass,直接调用findClass方法即可,虽然只能修改本地的class类
  3. findClass需要defineClass来最终把字节码文件加载进内存当中,JVM默认相同的类加载器不能加载相同全路径的类,所以每次重新加载的时候需要new一个自定义加载器,否则会报错
    String currentPath=Class.class.getClass().getResource("/").getPath()

    MyClassLoader myClassLoader=new MyClassLoader(currentPath);
    Class c=myClassLoader.findClass("com.test.Action.Test");
    
    MyClassLoader myClassLoader2=new MyClassLoader(currentPath);
    Class c2=myClassLoader2.findClass("com.test.Action.Test");

tomcat的类加载模型

  • tomcat本身也是一个依赖JDK的应用
  • tomcat/bin目录下有自己的jar包需要AppClassLoader加载:tomcat-juli.jar、bootstrap.jar等等
  • 每个独立的应用有自己的class路径,通过WebappClassloader加载,应用也依赖JDK的加载,所以应用的类加载机制:缓存加载-->AppClassLoader JDK系统加载-->自己加载-->父类加载
  1. 核心加载器
  • CommonClassLoader(默认父加载器为AppClassLoader)。加载一些tomcat/lib下面的jar包,servlet-api.jar、jsp-api.jar等
  • catalinaClassLoader(默认是空,有需要的话需要自己配置)
  • sharedClassLoader(默认是空,有需要的话需要自己配置)
  • WebAppClassLoader(tomcat下 WebRoot/应用程序/WEB-INF/lib 和 class包下的类
  1. 层级结构
  • tomcat下每个应用程序都有一个独立的类加载器,WebAppClassLoader,因为不同应用程序的类不能乱加载,更不能公用啊。
  • 但是有一些通用的类,比如JUnit、Log4j类,是不同应用程序公用的类,所以有sharedClassLoader出场,可以设置路径来实现这个类加载器,从而实现不同应用程序共同加载一些通用工具类
  • 再上一层就是CommonClassLoader:下面由shardClassLoader和CatalinaClassLoader,一个是所有应用程序,一个是tomcat容器的扩展类加载器
  • 再上一层就是AppClassLoader了,就是传统的模式往上走了
  1. 加载逻辑(源码 org.apache.catalina.loader.WebappClassLoader#loadClass)
    tomcat的类加载机制是违反了双亲委托原则的:先本地缓存查找,再全局缓存查找,再系统加载,再自己加载,最后再父加载器加载
  • 先在本地缓存中查找是否已经加载过该类(clazz = findLoadedClass0(name))
  • 再查询JVM缓存中查找是否已经加载过该类( clazz = findLoadedClass(name))
  • 让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖(tomcat bin下包)(clazz = system.loadClass(name))
  • web应用的类加载器将自行加载(findClass),这里也违背了双亲 (clazz = findClass(name);)
  • 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。(clazz = Class.forName(name, false, parentLoader);)

反射和Spring IOC

  • 反射是运行期编译,只有执行到这个方法,确定了参数:类名的时候才编译出对应的class文件,再加载到内存当中
    Class tc = Class.forName("com.java.dbtest.TestConnection");
  • CGLIB也是运行期编译,Enhancer类继承代理类,拦截相应的方法,实现代理

相关文章

  • 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/tkpkeqtx.html