java类加载器与双亲委托机制详解

先看jvm运行内存结构

java类加载器与双亲委托机制详解

 

 

1.•Java运行时编译源码(.java)成字节码,由jre运行。jre由java虚拟机(jvm)实现。Jvm分析字节码,后解释并执行java类加载器与双亲委托机制详解

2.类加载的过程

java类加载器与双亲委托机制详解

 

类加载:类加载器将class文件加载到虚拟机的内存

加载:在硬盘上查找并通过IO读入字节码文件

连接:执行校验、准备、解析(可选)步骤

校验:校验字节码文件的正确性

准备:给类的静态变量分配内存,并赋予默认值

解析:类装器装入类所引用的其他所有类

初始化:对类的静态变量初始化为指定的值,执行静态代码块

 

3.类加载器的种类

启动类加载器:负责加载JRE的核心类库,如jre目标下的rt.jar,charsets.jar等

扩展类加载器:负责加载JRE扩展目录ext中JAR类包

系统类加载器:负责加载ClassPath路径下的类包

用户自定义加载器:负责加载用户自定义路径下的类包

 

全盘负责委托机制当一个ClassLoader加载一个类时,除非显示的使用另一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入

双亲机制:指先委托父类加载器寻找目标类,在找不到的情况下自己的路径中查找并载入目标类

 

java类加载器与双亲委托机制详解

实现一个我们自定义类加载器 ,只需要继承ClassLoader即可

1.

public class MyClassLoader extends ClassLoader {

    private String path;
    private String classLoaderName;
    public MyClassLoader(String path,String classLoaderName) {
        this.path=path;
        this.classLoaderName=classLoaderName;
    }

    //寻找类文件
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] b = loadClassByte(name);
        return  defineClass(name,b,0,b.length);
    }
    //加载类文件
    private byte[] loadClassByte(String name){
        name=path+name+".class";
        InputStream in=null;
        ByteArrayOutputStream out=null;
        try{

            in=new FileInputStream(new File(name));
            out=new ByteArrayOutputStream();
            int i=0;
            while((i =in.read())!= -1){
              out.write(i);
            }
        }catch (Exception e){

        }finally {
            try {
                in.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();

 

2.

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
    MyClassLoader classLoader=new MyClassLoader("E://","myClassLoader");
    Class<?> c = classLoader.findClass("Demo");
    //System.out.println(c.toString());
    System.out.println(c.getClassLoader());
    c.newInstance();

}

 

双亲委派模式优势

沙箱安全机制:自己写的String.class类不会被加载,这样便可以防止核心API库被随意篡改

避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再   加载一次

 

我们可以自己定义String试试效果,看看classloader会不会给我们加载

java类加载器与双亲委托机制详解

java类加载器与双亲委托机制详解

 

效果很明显,我们自己定义的String类根本不能ClassLoader所加载,很好的证明了上面的二个理论.