JVM-类加载器

类加载器的树状层次结构

  • systems class loader
    用于加载java应用中的类,加载器为APPClassLoader
    如新建一个User类,这个类首先由APPClassLoader导入

  • Extensions Class Loader
    APPClassLoader的parent,用于加载jre/ext/*.jar

  • BootStrap class loader
    ExtClassLoader的parent,由C++实现,通过getParent()获取为null,

双亲委派机制

某个特定类加载器接收到加载请求后,首先将加载任务向其父类加载器委托,直至最父类加载器,如果最父类能够执行加载则成功返回,否则向下传递,由某个子类加载器执行加载

优点:

  • 保证java核心库的安全,不会因为用户编写的代码破坏java核心类

类加载过程

装载

查找并加载类的二进制数据

链接
  • 验证:确保类符合JVM规范,没有安全问题
  • 准备:为静态变量分配内存,并初始化为默认值
  • 解析:把虚拟机常量池中的符号引用转换为直接引用
初始化

为静态变量赋予正确的初始值

自定义类加载器

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
    private String rootPath;

    public MyClassLoader(String rootPath) {
        this.rootPath = rootPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //检查类是否已经加载
        Class<?> c = findLoadedClass(name);
        if(c!=null){
            return c;
        }
        //加载类
        byte[] data = getClassData(name);
        if(data==null){
            throw new ClassNotFoundException();
        }else{
            c = defineClass(name,data,0,data.length);
            return c;
        }
    }

    private byte[] getClassData(String className) {

        String path = rootPath+"/"+className.replace('.','/')+".class";
        InputStream is = null;
        ByteArrayOutputStream bos = null;
        try {
            is = new FileInputStream(path);
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int temp = 0;
            while((temp = is.read(buffer))!=-1){
                bos.write(buffer,0,temp);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                is.close();
                bos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

测试类:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        MyClassLoader loader = new MyClassLoader("C://zy");
        Class<?> c = loader.loadClass("test.Hello");
        Method m = c.getDeclaredMethod("test");
        m.invoke(c.newInstance());
        System.out.println();
    }
}
posted @ 2021-08-23 16:02  你也要来一颗长颈鹿吗  阅读(34)  评论(0)    收藏  举报