码迷,mamicode.com
首页 > 其他好文 > 详细

JVM类加载器

时间:2019-05-27 13:50:07      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:length   class   boot   ade   ext   set   this   委托   efi   

JVM默认的三个类加载器

技术图片

 

AppClasLoader  系统类加载器   

ExtClassLoader  扩展类加载器

BootstrapClassLoader  根类加载器  (由C++实现,在控制台打印出来的是null)

他们加载的jar包所在的路径不同

 

父委托机制

类加载是优先委托父加载器进行加载的,

AppClasLoader要加载一个类时,先找他的父加载器ExtClassLoader ,而ExtClassLoader先找他的父加载器BootstrapClassLoader ,先由根加载器加载类,找不到就由ExtClassLoader加载,

ExtClassLoader也找不到,就由AppClasLoader加载,AppClasLoader也找不到,会报错ClassNotFoundException

 

优点:防止内存中出现多份同样的字节码 ,不会去覆盖JVM底层自己定义的类,保证安全

缺点:父加载器的类对子加载器是可见的,但是子加载器的类对父加载器加载的类不可见

 

线程上下文类加载器

线程上下文类加载器可以避开父委托机制导致的子加载器的类对父加载器的类不可见的缺点

JDBC的接口是定义在java.sql 位于 java核心类库中,默认由根加载器加载

JDBC的接口的实现是放在classpath里的,默认是有系统类加载器加载,导致了根加载器的类对实现不可见

线程上下文类加载器加载了JDBC的接口,可以避免了接口看不见实现的问题

 

自定定义的类加载器(只是改变了类加载的路径,仍然是父委托机制)

public class MyClassLoader extends ClassLoader {

    private final static String DEFAULT_DIR = "C:\\Users\\xxx\\Desktop\\test\\";

    private String dir = DEFAULT_DIR;

    private String classLoaderName;

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
    }

    public String getClassLoaderName() {
        return classLoaderName;
    }
    
    public MyClassLoader() {
        super();
    }

    public MyClassLoader(String classLoaderName) {
        super();
        this.classLoaderName = classLoaderName;
    }

    public MyClassLoader(String classLoaderName, ClassLoader parent) {
        super(parent);
        this.classLoaderName = classLoaderName;
    }


    @Override
    protected Class<?> findClass(String name)
            throws ClassNotFoundException {
        String classPath = name.replace(".", "/");
        File classFile = new File(dir, classPath + ".class");
        if (!classFile.exists()) {
            throw new ClassNotFoundException("The class " + name + " not found under " + dir);
        }

        byte[] classBytes = loadClassBytes(classFile);
        if (null == classBytes || classBytes.length == 0)
            throw new ClassNotFoundException("load the class " + name + " failed");

        return this.defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] loadClassBytes(File classFile) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             FileInputStream fis = new FileInputStream(classFile)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


}

 

public class Test {

    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> cls = classLoader.loadClass("com.moreas.c527.SimObjec");
        System.out.println(cls.getClassLoader());
        System.out.println(cls.getClassLoader().getParent());

    }
}

 

JVM类加载器

标签:length   class   boot   ade   ext   set   this   委托   efi   

原文地址:https://www.cnblogs.com/moris5013/p/10930077.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!