Java反射--ClassLoader类加载器

内容学习于:edu.aliyun.com


1. 类加载器简介

  所有的Java程序的执行流程: JVM进程加载字节码文件,随后进行字节码文件的虚拟机解析,并且得到一个结果。
  经过分析可以发现,所有的“*.class"文件在磁盘上都会以二进制数据的形式保存(反射机制提供的就是二进制文件的解析能力),但是如果要想进行解析,那么首先要做到类的信息加载,于是在JDK之中针对于信息的加载提供有一个ClassLoader的加载器,如果要想观察ClassLoader可以直接利用Class类的方法来完成:

  • public ClassLoader getClassLoader()

  获得了ClassLoader之后就可以依据ClassLoader继续获取它之上的各个类加载器,也可以依据此ClassLoader找到对应的二进制字节码数据的信息,这个类里面重要的方法是获取父加载器: public final ClassL oader getParent()。

代码:

class Ball{}

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        System.out.println(Ball.class.getClassLoader());
        System.out.println(Ball.class.getClassLoader().getParent());
        System.out.println(Ball.class.getClassLoader().getParent().getParent());
    }
}

结果:

jdk.internal.loader.ClassLoaders$AppClassLoader@15db9742
jdk.internal.loader.ClassLoaders$PlatformClassLoader@85ede7b
null

  在Java之中为了防止程序可能出现的漏洞,例如:开发者自己定义了一个“java.lang.String”, 并且在里面安装有一些恶意的代码,那么请问,这个时候如何去防止这个恶性程序类被加载呢?所以在类加载器中专门提供了一个双亲加载机制,双亲加载指的是系统类使用系统类自己的加载器处理,而用户的类使用用户的加载器类进行处理,如果该类在系统类加载器中已经加载过了,那么用户加载器将不再加载重复的类。
  在JDK 1.8以前,不存在有“PlatformClassLoader", 而使用的是“ExtClassLoader”,主要是可以加载-一个第三方目录中的“*.jar” 文件,但是从JDK 1.9之后该加载器不再使用了。

2. 自定义类加载器

  ClassLoader类定义为抽象类,实际上如果有需要的开发者可以自己来定义专属的ClassLoader,假设现在有如下一个程序类。

定义消息处理类:

package com.xzzz.demo;

public class Message {
    public void send(String msg){
        System.out.println("【消息发送】"+msg);
    }
}

  2、为了更加方便的观察出ClassLoader特点,下 面将这个类手工进行编译(不打包),将生成的Message.class 文件保存在D盘。
  3、利用字节流进行二进制数据的加载,并且将加载到的内容转到ClassLoader之中,就是自定义类加载器。

自定义类加载器:

class ClassLoader extends java.lang.ClassLoader{
    private static final String CLASS_FILE = "D:" + File.separator + "Message.class";
    public Class<?> loadData (String classname) throws Exception{
        byte [] data = this.loadClassData();
        if (data!=null){
            return super.defineClass(classname,data,0,data.length);
        }
        return null;
    }


    private byte[] loadClassData() throws Exception{//加载数据
        InputStream input = new FileInputStream(CLASS_FILE);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        input.transferTo(bos);//加载文件到内存流
        byte [] data = bos.toByteArray();
        input.close();
        bos.close();
        return data;
    }
}

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = new ClassLoader();
        Class<?> clazz = classLoader.loadData("com.xzzz.demo.Message");
        Object object = clazz.getDeclaredConstructor().newInstance();
        Method method = clazz.getDeclaredMethod("send",String.class);
        method.invoke(object,"www.mldn.cn");
        System.out.println("【类加载器】"+clazz.getClassLoader());
        System.out.println("【类加载器】"+clazz.getClassLoader().getParent());
        System.out.println("【类加载器】"+clazz.getClassLoader().getParent().getParent());
        System.out.println("【类加载器】"+clazz.getClassLoader().getParent().getParent().getParent());
    }
}

结果:

【消息发送】www.mldn.cn
【类加载器】com.xzzz.demo.ClassLoader@4c873330
【类加载器】jdk.internal.loader.ClassLoaders A p p C l a s s L o a d e r @ 15 d b 9742 j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@15db9742 【类加载器】jdk.internal.loader.ClassLoaders AppClassLoader@15db9742jdk.internal.loader.ClassLoadersPlatformClassLoader@41629346
【类加载器】null

  这个最主要可以去操作远程的类,比如在加载网路服务器上的。
  在现实的对发之中,99%的情况下不需要开发者自定义类加载器,因为一旦定义多了,整个项目容易产生混乱。

全部评论

相关推荐

点赞 评论 收藏
分享
当年还在美团那个倒霉的&nbsp;Peppr&nbsp;团队工作时,我一直有个疑问:这群人每天到底在自嗨什么。每次开会一堆人围着一堆“看起来很高级”的文档转,模板统一、名词复杂、页数感人,每一页都在暗示一件事:“你不懂,是因为你不专业。”但现实是——代码照样写在&nbsp;💩&nbsp;山上,该出问题还是会出问题,这真的很逗,系统一出问题,文档的唯一作用就是证明:“我们当初确实认真写过文档。”所以本质区别到底是什么?是代码质量提升了,还是大家在精神层面完成了一次“工程师&nbsp;cosplay”?有句话说得好潮水退去才知道谁在裸泳。还记得当时的马哥、明哥(图&nbsp;1&nbsp;左)最爱反复强调一句话:“所有场景一定要想到。”、“这个场景为什么没考虑到?”不过他们这些话我是真的听进去了。不然我也不会在一年多前就说:这个项目活不过两年。顺带一提,那段时间还有个固定节目。每次下楼,总能听见我明哥在吐槽不同的人。我从他身后绕过去,经常能听到他一边抽烟一边说:“xx&nbsp;这小子太坑了,回头我一定要跟马哥说说。”于是深谙人情世故但真不会抽烟的我也会从口袋掏出一支低尼古丁含量的烟给自己点上,假意自己什么都没听到什么都不知道,只是来抽烟的。后来我才明白,这可能也是团队文化的一部分:问题永远在别人身上,而我们,永远在复盘里😂。
秋招白月光
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务