1,ClassLoader类加载器简介

  在Java里面提供一个系统的环境变量:ClassPath,这个属性的作用主要是在JVM进程启动的时候进行类加载路径的定义,在JVM里面可以根据类加载器而后进行指定路径中类的加载,也就是说找到了类的加载器就意味着找到了类的来源。

系统类的加载器

  如果说现在要想获得类的加载器,那么一定要通过ClassLoader来获取,而要想获取ClassLoader类的对象,则必须利用class类【反射的根源】实现,方法:public ClassLoader getClassLoader(),当获取了ClassLoader之后还可以继续获取其父类的ClassLoader类对象:public final ClassLoader getParent();

·范例:观察类加载器

  1. class Message {
  2. }
  3. public class JavaAPIDemo {
  4. public static void main(String[] args) {
  5. Class<?> clazz=Message.class;
  6. System.out.println(clazz.getClassLoader());//获取当前类的加载器
  7. System.out.println(clazz.getClassLoader().getParent());//获取父类加载器
  8. System.out.println(clazz.getClassLoader().getParent().getParent());//获取祖父类加载器
  9. }
  10. }
  11. /*
  12. jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
  13. jdk.internal.loader.ClassLoaders$PlatformClassLoader@1e643faf
  14. null
  15. */

  从JDK1.8之后的版本【JDK1.9和JDK1.10】提供有一个【PlatformClassLoader】类加载器,而在JDK1.8以及以前的版本里面提供的加载器为【ExtClassLoader】,因为在JDK的安装目录里面提供又一个ext的目录,开发者可以将【*.jar】文件拷贝到此目录里面,这样就可以直接执行了,但是这样的处理开发并不安全,最初的时候也是不提倡使用的,所以从JDK1.9开始将其彻底废除,同时为了和系统加载器与应用类加载器之间保持设计的平衡,提供有平台类加载器。

  当你获得了类加载器之后就可以利用类加载器来实现类的反射加载处理。

2,自定义ClassLoader处理

  清楚了类加载器的功能之后,就可以根据自身的需要实现自定义的类加载器,但是千万要记住一点:自定义类加载器其加载的顺序是在所有系统类加载器的最后。系统类中的加载器都是根据CLASSPATH找到的路径进行类加载的,而如果有了自定义类的加载器,就可以由开发者任意指派类的加载位置。

①随意编写一个程序类,并且将这个类保存在磁盘上;

  1. import java.io.*;
  2.  
  3. public class MufasaClassLoader extends ClassLoader {
  4. private static final String MESSAGE_CLASS_PATH="D:"+ File.separator+"Message.class";
  5. /**
  6. * 进行指定类的加载
  7. * @param className 类的完整名称【包.类】
  8. * @return 返回一个指定类的class对象
  9. * @throws Exception 如果类文件不存在则无法加载
  10. */
  11. public Class<?> loadData(String className)throws Exception{
  12. byte[] data=this.loadClassData();//读取二进制数据文件
  13. if(data!=null){//读取到数据
  14. return super.defineClass(className,data,0,data.length);
  15. }
  16. return null;
  17.  
  18. }
  19. private byte[] loadClassData()throws Exception{//通过文件进行类的加载
  20. InputStream input=null;
  21. ByteArrayOutputStream bos=null;//将数据加载到内存之中
  22. byte[] data=null;
  23. try{
  24. bos=new ByteArrayOutputStream();//实例化内存流
  25. input=new FileInputStream(new File(MESSAGE_CLASS_PATH));//文件流加载
  26. // byte[] data=new byte[1024];//进行读取方式①
  27. input.transferTo(bos);//读取数据方式②
  28. data= bos.toByteArray();//将所有读取到的字节数组取出
  29. }catch (Exception e){
  30.  
  31. }finally {
  32. if(input!=null){
  33. input.close();
  34. }
  35. if(bos!=null){
  36. bos.close();
  37. }
  38. }
  39. return data;
  40. }
  41. }

④编写测试类实现类加载控制;

  1. package cn.mufasa.demo;
  2. import cn.mufasa.util.MufasaClassLoader;
  3. import java.lang.reflect.Method;
  4.  
  5. public class JavaAPIDemo1 {
  6. public static void main(String[] args) throws Exception {
  7. MufasaClassLoader classLoader=new MufasaClassLoader();
  8. Class<?> cls=classLoader.loadData("cn.mufasa.util.Message");//进行类的加载
  9. System.out.println(cls);
  10. Object obj=cls.getDeclaredConstructor().newInstance();
  11. Method method=cls.getDeclaredMethod("send");
  12. method.invoke(obj);
  13. }
  14. }
  15. /*
  16. 读取到数据
  17. class cn.mufasa.util.Message
  18. www.cnblogs.com
  19. */

  如果在以后结合网络开发的话,就可以通过一个远程的服务器来确定类的功能。

⑤观察当前的Message类的加载器的情况

  1. package cn.mufasa.demo;
  2. import cn.mufasa.util.MufasaClassLoader;
  3. import java.lang.reflect.Method;
  4.  
  5. public class JavaAPIDemo1 {
  6. public static void main(String[] args) throws Exception {
  7. MufasaClassLoader classLoader=new MufasaClassLoader();
  8. Class<?> cls=classLoader.loadData("cn.mufasa.util.Message");//进行类的加载
  9. // System.out.println(cls);
  10. System.out.println(cls.getClassLoader());//获取当前类的加载器
  11. System.out.println(cls.getClassLoader().getParent());//获取父类加载器
  12. System.out.println(cls.getClassLoader().getParent().getParent());//获取祖父类加载器
  13.  
  14. }
  15. }
  16. /*
  17. cn.mufasa.util.MufasaClassLoader@668bc3d5
  18. jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
  19. jdk.internal.loader.ClassLoaders$PlatformClassLoader@3fb6a447
  20. */

  如果说你先在定义了一个类,这个类的名称定义为:java.lang.String,并且利用了自定义类加载器进行加载处理,这个类将不会被加载,原因:Java之中针对于类加载器提供有双亲加载机制,如果现在要加载的类是由系统提供的类则会由系统类进行加载,如果现在开发者定义的类与系统类定义的名称相同,那么【为了保证系统的安全性】绝对不会加载。

进阶Java编程(11)ClassLoader类加载器【待完成】的更多相关文章

  1. Java安全之 ClassLoader类加载器

    Java安全之 ClassLoader类加载器 0x00 前言 前面这里抛出一个问题,Java到底是什么类型的编程语言?是编译型?还是解释型?在这个问题是其实一直都都有疑惑,如果说是解释型语言的话,那 ...

  2. Java URLClassLoader 和 ClassLoader类加载器

    开始:看名字都带有ClassLoader,叫做类加载器,事实上是可以理解为动态的加载类,不过,也不是只能加载类,也可以加载其他形式的文件,比如说.properties属性文件. 区别:其实在两个类加载 ...

  3. Java中对于ClassLoader类加载器 嵌套了深度技术的价值

    关于Java技术是一种不断兴起的编程语言,对于ClassLoader 是 Java 届最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里.本文我带你彻底吃透 ClassLoader,让你甚 ...

  4. 【原创】Java基础之ClassLoader类加载器简介

    classloader简介 1 classloader层次结构(父子关系) Bootstrap(ClassLoader) ExtClassLoader AppClassLoader XXXClassL ...

  5. ClassLoader类加载器 & Java类加载机制 & 破坏双亲委托机制

    ClassLoader类加载器 Java 中的类加载器大致可以分成两类: 一类是系统提供的: 引导类加载器(Bootstrap classloader):它用来加载 Java 的核心库(如rt.jar ...

  6. 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题…..

    1.类加载过程 类加载时机 「加载」 将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存上创建一个java.lang.Class对象用来封装类在方法区内的数据 ...

  7. 【Java虚拟机3】类加载器

    前言 Java虚拟机设计团队有意把类加载阶段中的"通过一个类的全限定名来获取描述该类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类. ...

  8. java ClassLoader类加载器

    原文 首先来了解一下字节码和class文件的区别: 我们知道,新建一个java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java ...

  9. java 反射,类的加载过程以及Classloader类加载器

    首先自定义一个类Person package reflection; public class Person { private String name; public int age; public ...

随机推荐

  1. ARP输入 之 arp_process

    概述 arp_process为ARP输入包的核心处理流程: 若输入为ARP请求且查路由成功,则进行如下判断:输入到本地,则进行应答:否则,允许转发,则转发,本文代码不包含转发流程: 若输入为ARP应答 ...

  2. Python中调用shell

    1 简单调用shell命令 os.system(command) 在一个子shell中运行command命令, 并返回command命令执行完毕后的退出状态. 这实际上是使用C标准库函数system( ...

  3. uni-app 的更新及碰到的问题

    uni-app 的更新 我这个是针对 app 的测试,没有考虑 小程序 及 h5,如需考虑请参考 uni-app 的条件编译 当我们将文件打包好之后,我们在手机上就可以下载 apk 文件,安装到我们的 ...

  4. Flutter移动电商实战 --(8)dio基础_伪造请求头获取数据

    在很多时候,后端为了安全都会有一些请求头的限制,只有请求头对了,才能正确返回数据.这虽然限制了一些人恶意请求数据,但是对于我们聪明的程序员来说,就是形同虚设.这篇文章就以极客时间 为例,讲一下通过伪造 ...

  5. kotlin class

    每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托.委托到同一个类的另一个构造函数用 this 关键字即可 class Person { constructor(pare ...

  6. Elasticsearch的安装入门

    大纲: 一.简介 二.Logstash 三.Redis 四.Elasticsearch 五.Kinaba 一.简介 1.核心组成 ELK由Elasticsearch.Logstash和Kibana三部 ...

  7. SQL Server 新建 数据库关系图 时弹出警告提示此数据库没有有效所有者,因此无法安装数据库关系图支持对象。

    今天创建数据库关系图,发现提示此数据库没有有效所有者,因此无法安装数据库关系图支持对象.若要继续,请首先使用 数据库属性 对话框的文件页或 ALTER AUTHORIZAITION 语句将数据库所有者 ...

  8. HTML <a> 标签的 href 属性_定位资源

    * 定位资源 ** 如果想要定位资源:定义一个位置 <a name="top">顶部</a> ** 回到这个位置 <a href="#top ...

  9. Vue 子组件与子组件之间传值

    可以借用公共父元素.子组件A  this.$emit("eventName", data) 触发事件,父组件监听事件,更改父组件 data , 通过Props 传值到子组件B,子组 ...

  10. playbook文件内容解释

    [root@node1 playbook]# cat nginx.yml - hosts: test \\主机组,要和nginx.yml在同一个目录下 remote_user: root \\远端执行 ...