千家信息网

JVM中classloader的作用是什么

发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,这篇文章主要讲解了"JVM中classloader的作用是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"JVM中classloader的作用是什么
千家信息网最后更新 2025年02月04日JVM中classloader的作用是什么

这篇文章主要讲解了"JVM中classloader的作用是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"JVM中classloader的作用是什么"吧!

方法

  • public Class loadClass(String name) throws ClassNotFoundException 通过类名发挥这个类的Class实例

  • protected final Class defineClass(byte[] b,int off,int len) 根据给定的字节码流 b,off 和 len 参数表示实际的 class 信息在byte 数组中的位置和长度,其中 byte 数组 b是 classloader 从外部获取的

  • protected Class findClass(String name)throws ClassNotFoundException 查看一个类

  • protected final Class findLoadedClass(String name)

分类

  • BootStrap ClassLoader

  • Extension ClassLoader

  • AppClassLoader 启动类加载器负责加载系统的核心类(rt.jar的java类),扩展类加载器加载 %JAVA_HOME/lib/ext/*.jar中的类,应用类加载器用于加载用户类 (classpath),自定义类加载器加载一些特殊路径的类(自定义classloader)

双亲委托

  1. 当前 classloader 首先从自己已经加载的类中查询是否此类已经加载,如果已经加载了则直接返回原来已经加载的类

  2. 当前 classloader 的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查下自己的缓存,然后委托父类去加载,一直到 bootstrap classloader

  3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入自己的缓存中,下次请求的时候直接返回

  4. 一直循环重复

作用

  • 各个类加载器的基础类统一

jar -cvf test.jar HelloLoader.class 把class打包成jar

Extension ClassLoader

例子:在 ext 路径下放一个自己 jar 包并加载

package com.mousycoder.server;public class HelloWorld {    public static void main(String[] args) {        System.out.println("Hello World!");    }}

idea 通过 structs->artifacts->jar 然后 build-> build artifacts->build 生成 helloworld.jar 放到 /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/ext

package com.mousycoder.mycode.thinking_in_jvm;import java.lang.reflect.Method;/** * @version 1.0 * @author: mousycoder * @date: 2019-09-06 10:35 */public class ExtClassLoader {    public static void main(String[] args) throws ClassNotFoundException {        System.out.println(System.getProperty("java.ext.dirs"));        Class helloClass = Class.forName("com.mousycoder.server.HelloWorld");        System.out.println(helloClass.getClassLoader());    }}

输出

/Users/mousycoder/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/javasun.misc.Launcher$ExtClassLoader@610455d6

可以看出是 ExtClassLoader 加载 java.ext.dirs 目录

自定义类加载器

package com.mousycoder.mycode.thinking_in_jvm;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;/** * @version 1.0 * @author: mousycoder * @date: 2019-09-06 11:13 */public class MyClassLoader extends ClassLoader {    private final static Path DEFAULT_CLASS_PATH = Paths.get("","/Users/mousycoder/My");    private final Path classDir;    public MyClassLoader(){        super();        this.classDir = DEFAULT_CLASS_PATH;    }    public MyClassLoader(String classDir){        super();        this.classDir = Paths.get(classDir);    }    public MyClassLoader(String classDir, ClassLoader parent){        super(parent);        this.classDir = Paths.get(classDir);    }    @Override    protected Class findClass(String name) throws ClassNotFoundException {        try {            byte[] classBytes = this.readClassBytes(name);            if (null == classBytes || 0 == classBytes.length){                throw new ClassNotFoundException("can not load the class" + name);            }            return this.defineClass(name,classBytes,0,classBytes.length);        } catch (IOException e){            e.printStackTrace();        }        return null;    }    private byte[] readClassBytes(String name) throws ClassNotFoundException, IOException {        String classPath = name.replace(".","/");        Path classFullPath = classDir.resolve( "HelloWorld1.class");        if (!classFullPath.toFile().exists()){            throw new ClassNotFoundException("The class" + name + "mpt found");        }        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){            Files.copy(classFullPath,baos);            return baos.toByteArray();        } catch (IOException e){            throw new ClassNotFoundException("load the class " + name + "occur error",e);        }    }    @Override    public String toString() {        return "My ClassLoader";    }}package com.mousycoder.mycode.thinking_in_jvm;/** * @version 1.0 * @author: mousycoder * @date: 2019-09-06 11:34 */public class MyClassLoaderTest {    public static void main(String[] args) throws ClassNotFoundException {        MyClassLoader classLoader = new MyClassLoader();        Class class1 = classLoader.loadClass("com.mousycoder.mycode.thinking_in_jvm.HelloWorld1");        System.out.println(class1.getClassLoader());    }}package com.mousycoder.mycode.thinking_in_jvm;/** * @version 1.0 * @author: mousycoder * @date: 2019-09-06 11:46 */public class HelloWorld1 {    public static void main(String[] args) {        System.out.println("Hello world1 ");    }}

把helloword1变成class放到/Users/mousycoder/My目录下即可 输出 My ClassLoader 代表 自定义类加载器加载了该类

上下文类加载器

作用

打破双亲委托机制,让上层父类加载器可以使用子类的加载器加载对象,比如Spi中的接口类在系统加载器中,但是实现类在应用加载器中

Tomcat 类加载器

目的

  1. 保证每个应用的类库独立隔离(即使同限定名不同版本的)

  2. 保证相同类库相同版本的类库共享

  3. 保证容器自身的类库和程序独立

加载顺序

  1. bootstrap 引导类加载器

  2. system 系统类加载器

  3. 应用类加载器 WEB-INF/classes

  4. 应用类加载器 WEB-INF/lib

  5. common 类加载器 CATALINA/lib

感谢各位的阅读,以上就是"JVM中classloader的作用是什么"的内容了,经过本文的学习后,相信大家对JVM中classloader的作用是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0