ClassLoader类加载器

Class类描述的整个类的信息,在Class类中提供的forName()方法是根据ClassPath配置的路径进行类的加载,日过现在需要加载的类的路径是文件或者网络,这个时候就需要实现类加载器,也就是ClassLoader起作用.

1.ClassLoader类加载器

定义如下

public ClassLoader getClassLoader()

然后编写一个简单的程序来观察一下ClassLoader的存在

package ClassLoader;

/**
 * Author:weiwei
 * description:ClassLoader类加载器
 * Creat:2019/1/26
 **/

class Member{}
public class ClassLoader1 {
    public static void main(String[] args) {
        Class<?> cls=Member.class;
        System.out.println(cls.getClassLoader());
        System.out.println(cls.getClassLoader().getParent());
        System.out.println(cls.getClassLoader().getParent().getParent());
    }
}
jdk.internal.loader.ClassLoaders$AppClassLoader@4629104a
jdk.internal.loader.ClassLoaders$PlatformClassLoader@f5f2bb7
null

运行结果如上所示,此时出现了两个类加载器,APPClassLoader(应用程序类加载器),PlatformClassLoader(平台类加载器),

那么,什么是类加载器呢?

类加载器基础概念

简单来说,Classloader 类加器,用来加载Java类到 Java 虚拟机中的一种加载器。

用一张图了解一下ClassLoader

  • 因为Java程序(class文件)与其他程序不同,不是本地可执行程序,当运行Java程序时,先运行JVM(Java虚拟机),然后再把Class类加载到JVM里面运行,负责加载Java Class的这部分就叫做ClassLoader(类加载器)
  • JVM本身包含了一个ClassLoader叫做Bootstrap ClassLoader(启动类加载器),Bootstrap ClassLoader是使用C++实现的,无法被Java程序直接引用,它负责加载核心JavaClass(即所有Java.*开头的类)
  • 另外JVM还提供了两个类加载器,ExtClassLoader(扩展类加载器),AppClassLoader(应用程序类加载器),它们都是由Java语言编写的,ExtClassLoader负责加载扩展的ClassLoader(例如Java.*开头的类和存放在JRE的ext目录下的类),开发者可直接使用扩展类加载器,APPClassLoader负责加载应用程序自身的类,如果应用程序中没有自定义自己的类加载器,则此加载器就是程序中默认的类加载器.

2.双亲委派模型

什么是双亲委派模型?

如上图所示,各类加载器之间的层次关系,就称为类加载器的双亲委派模型,双亲委派模型要求除了顶层的父类加载器外,其他的类加载器都应该有自己的父类加载器.

双亲委派模型的工作流程:如果一个类加载器收到了一个类加载请求,它首先不会自己尝试去加载这个类,而是把这个请求委托给父类加载器去完成,每一层次的类加载器都是如此,因此,所有的加载请求都应当传送到顶层的Bootstrap加载器中,只有当父类加载器反馈无法完成这个加载请求时(在自己的搜索范围内没有找到这个类),子加载器才会尝试自己去加载.

3.自定义类加载器

自定义类加载器:用户决定类从哪里加载

进行类加载的方法:

protected Class<?> loadClass(String name,boolean resolve)
           throws ClassNotFoundException

自定义类加载器

package com.bittech.reflect.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Author: weiwei
 * Created: 2019/1/27
 * Description: 自定义类加载器
 */
public class MyClassLoader extends ClassLoader {
    
    
    public Class<?> loadData(String name) throws ClassNotFoundException {
        try {
            byte[] classData = loadClassByte(name);
            return this.defineClass(name, classData, 0, classData.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }
    
    
    //name类 -> .class
    //.class文件通过文件读取的方式变成byte[]
    private byte[] loadClassByte(String name) {
        //classpath + classname
        File file = new File("E:\\Member.class");
        try (FileInputStream inputStream = new FileInputStream(file);
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
        ) {
            byte[] buff = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
            }
            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

类加载器给用户提供的最大的帮助是:可以通过动态的路径进行类的加载操作

比较两个类相等的前提是:必须由同一个类加载器锁加载,否则即使两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类注定不相等.

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值