JVM类加载器的认识

对类的加载器进行认识:
public class ClassLoaderTest {
     public static void main(String[] args) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        System.out.println(loader);
        System.out.println(loader.getParent());
        System.out.println(loader.getParent().getParent());
    }
}
sun.misc.Launcher$AppClassLoader@64fef26a
sun.misc.Launcher$ExtClassLoader@1ddd40f3
null
        会发现,找到了ApplicationClassLoader和ExtClassLoader,但是没有找到ExtClassLoader的父加载器BootstrapClassLoader,原因是BootstrapClassLoader使用C语言实现的,并不是用java语言做的,所以是不能返回一个确定的父加载器的方法,所以才返回了NULL。
        而在Java中,类加载器的结构为:
                          
            
         注意:这里的父类加载器并不是通过集成的方式来实现的,而是通过类组合的方式实现的。
         
        类加载器大致分为三类:

        第一、启动类加载器。(BootStrapt ClassLoader)
        启动类加载器,负责加载存放在JDK/jre/lib目录下的类库,比如:rt.jar。启动类加载器是无法被Java程序直接引用的。

        第二、扩展类加载器。(Ext ClassLoader)
        扩展类加载器,负责加载JDK/jre/lib/ext目录下的所有类库。开发者是可以直接使用扩展类加载器。

        第三、应用程序类加载器。(Application ClassLoader)
        应用程序类加载器,负责加载用户类路径(classpath)所指定的类,开发者可以直接使用该类加载器,如果引用程序没有自定义过自己的类加载器,一般情况这就是程序默认的类加载器。

        同时,可以实现自定义类加载器:
        通常情况下,我们都是直接使用系统自带的类加载器。但是,有的时候,我们也需要自定义类加载器。那图和实现呢?
        自定义类加载器一般都是继承自ClassLoader类,从上面对loadClass方法来分析看,只需要重写findClass方法即可。
        自定义类加载器的应用场景:比如对字节码进行了加密之后,可以通过自定义类加载器来实现解密。
        
package com.hui;

import java.io.*;

public class MyClassLoader extends ClassLoader {
    private String root;
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = loadClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    private byte[] loadClassData(String className) {
        String fileName = root + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
        try {
            InputStream ins = new FileInputStream(fileName);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            int length = 0;
            while ((length = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getRoot() {
        return root;
    }

    public void setRoot(String root) {
        this.root = root;
    }

    public static void main(String[] args)  {
        MyClassLoader classLoader = new MyClassLoader();
        classLoader.setRoot("E:\\temp");
        Class<?> testClass = null;
        try {
            testClass = classLoader.loadClass("com.neo.classloader.Test2");
            Object object = testClass.newInstance();
            System.out.println(object.getClass().getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
        











全部评论

相关推荐

10-09 00:50
已编辑
长江大学 算法工程师
不期而遇的夏天:1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
牛客771574427号:恭喜你,华杰
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务