类加载器 ClassLoader

类加载器 ClassLoader

1.什么是类加载器?有什么作用?
2.类加载器的分类(根、扩展、应用、自定义)
3.加载方式(显式、隐式)
4.自定义类加载器
5.网络类加载器

==================================================
说白了:根据条件得到.class文件,后面我们利用反射技术取.class中的属性和方法
委托、可见性、单一性、安全

d:\\Abc.class
==================================================
1.什么是类加载器

  问题一:实例化对象的方式:
  a、直接new:通过模板进行实例化
  b、通过类加载器来实现

  问题二:类的来源
  a、我们自己写的类
  b、导入的jar包中的类
  c、JDK中自带的类库

  所谓类加载器就是用来加载Java类到Java虚拟机中,又称为“类类”。
  说明了:就是负责将.class字节码文件送到JVM中运行的类。

  Java虚拟机使用Java类的方式:
  Java源程序(.java文件)在经过Java编译器编译之后被转换在Java字节码(.class文件),类加载器就负责读取Java字节码,并转换成java.lang.Class类的一个实例。

  每个这样的实例用来表示一个Java类,通过此实例的newInstance()方法可以创建出该类的一个对象。实际情况可能更复杂。

  说白了:我们写的源文件.java先通过编译器(javac)编释成类文件,然后送到JVM虚拟机去执行,谁送它去JVM虚拟机?就是类加载器。


  注意:
  a. 类加载器本身就是一个类。
  b. 类加载器责责加载文件系统、网络或其他来源的类文件。
  c. 基本上所有的类加载器都是java.lang.ClassLoader类的一个实例。

-------------------------------------
 java.lang.ClassLoader类:
  
  方法:
  getParent()        
    //返回该类加载器的父类加载器

  loadClass(String n)    
    //加载名称为n的类,返回的结果是java.lang.Class类的实例

  findClass(String n)    
    //查找名称为n的类,返回的结果是java.lang.Class类的实例

  findLoaderClass(String n)    
    //查找名称为n的已被加载过的类,返回的结果是java.lang.Class类的实例

  defineClass(String n, byte[] b, start, end)
      // 把字节数组b中的内容转换成Java类,返回实例,该方法被声明为final

  resolveClass(Class<?> c)
    //链接指定的Java类

-------------------------------------------------
Class.forName(xxx.xx.xx); //要求JVM查找并加载指定的类

如何查看谁加载的对象(类加载器)
System.out.println(对象名.getClass().getClassLoader());

如何查看类加载器的父类
System.out.println(对象名.getClass().getClassLoader().getParent());

user.getClass().getClassLoader();//根据对象名得到它的类加载器
String.class.getClassLoader();    //根据类名得到它的类加载器
user.getClass().getClassLoader().getParent();

================================================

2.类加载器的分类

  根类加载器
  扩展类加载器
  应用类加载器
  自定义类加载器


  2.1 根类加载器(null):也称引导加载器
      该加载器没有父加载器,它是所有类加载器的父加载器。
      负责加载虚拟机的核心类库(JRE/lib/rt.jar中的JDK类文件)。
      
      返回null的基本上就是根加载器,也有可能是其它的。

  2.2 扩展类加载器(Ext):
      其父加载器为根类加载器。
      负责从java.ext.dirs系统属性所指定的目录中加载类,
      或者从JDK安装目录的jre/lib/ext子目录下加载类库。

      将加载类的请求先委托给它的父加载器,也就是Bootstrap,如果没有成功加载,再从jre/lib/ext或者java.ext.dirs系统属性定义的目录下加载类。
      System.out.println(User.getClass().getClassLoader().getParent());
      //返回:……ExtClassLoader……


  2.3 应用类加载器(App):
      也称为系统类加载器,它的父加载器为扩展类加载器。
      负责加载我们自己写的类,它是用户自定义类的默认父加载器。
      System.out.println(User.getClass().getClassLoader());
      //返回:……AppClassLoader……


  2.4 自定义类加载器
  类加载器之间的关系:
  根类加载器  ——>  扩展类加载器  ——>  应用类加载器   ——>  自定义类加载器
   (爷爷)            (父亲)             (儿子)             (儿子的儿子)


=================================================

3.加载方式分类
  3.1 显式加载(字符串模式)
    Class c = Class.forName("com.temp.Person");
    Person p = (Person)c.newInstance();

  3.2 隐式加载
    Person p = new Person();

==================================================

4.自定义类加载器
    自己写个类加载器,加载指定路径中的类。
    比如有个类的.class文件不在项目中,如何加载?例如加载d:\\com\\entity\\User.class


  操作步骤:
  (1)创建类,继承类加载器ClassLoader,要拥有类加载器的所有功能。
  (2)重写查找类的方法findClass()。
      参数:String name 表示要加载的类的路径
      Class<?>:找到文件后,再返回该类的.class文件
               (有技术点:将文件转化成Class文件)

//代码:
public class MyClassLoader extends ClassLoader {
    
//重写查找类的方法
    
/**
* String name  要加载的文件的的路径
* Class<?>    找到文件后  再返回(将文件流 转换为一个class)
*/

protected Class<?> findClass(String name) throws ClassNotFoundException {
    // TODO Auto-generated method stub

    //1.找到.class文件的路径(假设e:\cs\com\entity\User.cs文件)
    // 将类的路径字符串中的“.”过滤成“/” 
    String str=name.replaceAll("\\.", "/");

    // 指定要加载的文件路径
    str="e:\\cs\\"+str+".cs";
    
    //2.声明一个Class,用于接收类转换的class文件
    Class c=null;
    try {
        //将文件流转换成class文件
            FileInputStream fis=new FileInputStream(str);

        //声明一个数组  其大小要刚好与文件大小相同
        byte[] bs=new byte[fis.available()]; //fis.available()文件长度

        //将文件内容读取到bs中
        fis.read(bs);
        
        //重点:将字节流转换为其对应的Class
        c=this.defineClass(null, bs, 0, bs.length);

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return c;
    }
}

  (3)利用自定义加载器去加载非项目里面的字节码
    //先声明并实例化一个自定义类加载器
    MyClassLoader  mcl = new MyClassLoader();
    //指定类加载器(mcl)
    Class c = Class.forName("com.entity.Person", true, mcl); 
    System.out.println(c.getClassLoader());


========================================

5.网络类加载器:

  案例:将User.class放到Tomcat/webapp/temp/中。

  //声明一个网址对象
  URL url = new URL("http://localhost:8080/temp/");

  //声明一个网络类加载器,这里可以加载一组,但这我们只放了一个
  URLClassLoader  ucl = new URLClassLoader(new URL[]{url});

  //利用网络类加载器去加载指定的类
  Class c = Class.forName("com.entity.Person", true, ucl);

  System.out.println(c.getClassLoader());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

银色亡灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值