java class loader学习笔记

1.class loader是什么?

负责将java字节码.class文件加载入jvm,生成Class对象,存入内存,才能使用(new),才可以创建该Class的Obj对象。

2.class loader工作包含哪些流程?

1、装载:查找和导入Class文件 
2、链接:其中解析步骤是可以选择的 
(a)检查:检查载入的class文件数据的正确性 
(b)准备:给类的静态变量分配存储空间 
(c)解析:将符号引用转成直接引用 
3、初始化:对静态变量,静态代码块执行初始化工作

3.有哪些默认class loader

 1Bootstrap ClassLoader  启动类加载器,jvm自带 c语言编写,无java源码,负责加载jdk核心jar。
 2ExtClassLoader 扩展类加载器,负责加载jdk中ext文件夹下class
 3AppClassLoader 应用类加载器,负责加载应用程序项目class加载。

4.默认类加载器如何协调工作。

新加载任务->到3号->传递2号->传递11号有,不加载,没有传递给22号有,不加载,没有传递给33号有,不加载,3号没有,加载。

5.核心方法

1、 loadClass(String name,boolean resovle ) 加载class入口
2、 findClass(String name) 查询class文件跟defineClass连用
3、 defineClass(String name,byte[] data,int off,int length) 将class文件字节数据载入内存

6.demo

import java.io.*;
import java.util.concurrent.TimeUnit;

public class MyClassLoader extends ClassLoader {

    //    window系统存放地址
    private static final String WIN_ROOT_DIR = "D:\\plugins";
    //    linux系统存放地址
    private static final String LIN_ROOT_DIR = "/home/java/plugins";


    /**
     * 加载class对象
     * 默认实现为 先去父loader找,找到就不加载,找不到才在自己这找
     * 若要实现替换旧的,就不能先去父loader找,因为在app loader中可能已经存在,
     * 这样就不会再加载。所以要先在自己这找,找不到才去父里找。
     *
     * @param name
     * @param resolve
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        Class<?> result = findClass(name);
        if (result == null) {
            return super.loadClass(name, resolve);
        }
        if (resolve) {
            resolveClass(result);
        }
        return result;
    }

    /**
     * 寻找class文件所在并调用defineClass方法加二进制文件载入内存。
     *
     * @param name 加package的Class名
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] data = loadByte(name);
        if (data == null) {
            return null;
        }
        return defineClass(name, data, 0, data.length);
    }

    /**
     * 获取class文件存放根路径
     *
     * @return
     */
    private static String getRootDir() {
        if (File.separatorChar == '\\') {
            return WIN_ROOT_DIR;
        }
        return LIN_ROOT_DIR;
    }

    /**
     * 将class文件转为byte[]
     *
     * @param name
     * @return
     */
    private byte[] loadByte(String name) {
        if (null == name || name.isEmpty()) {
            return null;
        }
        StringBuilder builder = new StringBuilder(name);
        for (int index = builder.indexOf("."); index != -1; index = builder.indexOf(".")) {
            builder.replace(index, index + 1, File.separator);
        }
        String uri = builder + ".class";
        String url = getRootDir() + File.separator + uri;
        File file = new File(url);
        if (!file.exists()) {
            return null;
        }
        try (FileInputStream input = new FileInputStream(file);
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] temp = new byte[1024];
            for (int index = input.read(temp); index != -1; index = input.read(temp)) {
                out.write(temp, 0, index);
            }
            out.flush();
            return out.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //    测试
    public static void main(String[] args) throws ClassNotFoundException, 
    IllegalAccessException, InstantiationException, InterruptedException {
        while (true) {
            MyClassLoader loader = new MyClassLoader();
            Class<?> clazz = loader.loadClass("Test", true);
            Object o = clazz.newInstance();
            System.out.println(o);
            TimeUnit.SECONDS.sleep(1);
        }

    }
}

测试类Test,只要重写toString()返回不同的字符串值即可。

阅读更多

扫码向博主提问

自强不惜

君子爱财
去开通我的Chat快问
文章标签: java class loader
个人分类: java基础
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭