ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【深入浅出-JVM】(76):classloader

2019-09-16 19:02:15  阅读:164  来源: 互联网

标签:String mousycoder name classloader class 76 JVM public 加载


方法

  • 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/java
sun.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

标签:String,mousycoder,name,classloader,class,76,JVM,public,加载
来源: https://www.cnblogs.com/mousycoder/p/11528992.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有