java基础-类加载器:实现一个类加载器

版权声明:中华人民共和国持有版权 https://blog.csdn.net/Fly_Fly_Zhang/article/details/84317714
    1,如何识别class文件?
    通过MD5加密算法
    2,加载:
    启动类加载器:Bootstrap Classloade>加载 jre/lib/rt.jar   :主要有Object,String等类
    扩展类加载器:ExtClassLoader>加载jre/lib/ext/*  jar 主要是JAVA_HOME/jre/lib/ext 路径下的jar包

应用类加载器:AppClassLoader>加载classpath路径下所有的jar和目录 加载自己所写的类

      通过类加载器:
            class

loadclass方法:负责以双亲委托的方式去加载类
findclass方法:根据类的包路径找到class文件
defineclass:负责从字节码中加载class对象,然后class对象通过反射机制生成对象。
findclass次数<=loadclass次数
如何实现一个类加载器?
不能够破坏双亲委派模型
重写一个方法: findclass() //其他两个不能重写。重写loadclass会破坏双亲委派模型。defineclass只有包权限,只能源码调用。

import java.io.*;

/**
* @Created with IntelliJ IDEA
* @Description:
* @Package: PACKAGE_NAME
* @User: FLy
* @Date: 2018/11/21
* @Time: 10:20
*/
class MyClassLoader extends ClassLoader{

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //TODO Auto-generated method stub
        String Dir="D:";//用户自定义路径进行拼接
        String classPath=Dir+File.separatorChar+name.replace('.',File.separatorChar)+".class";
        File file= new File(classPath);
        byte[] buff=null;
        InputStream in;
        try{
            in=new FileInputStream(file);
            buff=new byte[in.available()];
            in.read(buff);
            in.close();
            Class<?> c=defineClass(name,buff,0,buff.length);
            return c;
        }catch (FileNotFoundException e){
            //TODO Auto-generated catch block
            e.printStackTrace();
        }catch(IOException e) {
            //TODO Auto-generted catch block
            e.printStackTrace();
        }
        return super.findClass(classPath);
    }
}

双亲委派模型的好处:
1.
安全性:避免用户自己编写的类动态替换java中的一些核心类。如果不采用双亲委派模型的加载方式进行类的加载工作,那我们就可以随便使用自己定义的类来动态的替换java核心API中定义的类。 而双亲委派模型的这种加载方式就可以避免这种情况,因为String类在启动时就被启动类加载器进行加载。
2.
避免类的重复加载;因为JVM判定两个类是否是同一个类,不仅仅根据类名是否相同进行判定,还需要判断加载该类的加载器是否是同一个加载器。相同的class文件被不同的类加载器进行加载得到的结果就是不同的类。
3.
JAVA类随着它的类加载器一起具备了一种带有优先级的层次关系。例如Java。lang.Object。它存在于rt.jar中,无论哪一个类加载器要加载这个类,最终都委派给处于模型顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反如果没有双亲委派模型,而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在classPath中,那么系统中将会出现多个不同的Object类,程序将混乱。因此。如果开发者尝试编写一个与rt.jar类库中重名的java类,可以正常编译,但无法被加载运行

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Fly_Fly_Zhang/article/details/84317714