首页 > 其他 > 详细

类加载器

时间:2020-12-12 23:31:59      阅读:43      评论:0      收藏:0      [点我收藏+]

一、类加载过程

技术分享图片

一个非数组类的加载阶段(加载阶段通过一个类的全限定名来获取描述此类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 loadClass() 方法),这个动作放到Java虚拟机外部去实现数组类型不通过类加载器创建,它由 Java 虚拟机直接创建

类加载器用于实现类的加载动作。

二、

package JvmTest;

import java.io.IOException;
import java.io.InputStream;

/*
 * 类加载器与instanceof关键字演示
 *   (1)Java序列化就是指把Java对象转换为字节序列的过程
 *   (2)Java反序列化就是指把字节序列恢复为Java对象的过程。
 */
public class Nine {
    public static void main(String[] args) throws Exception{
        //自己重写的类加载器
        ClassLoader myLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                try{
                    //加载在同一路径下Class文件
                    String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                    InputStream is = getClass().getResourceAsStream(fileName);

                    if(is == null){
                        return super.loadClass(name);
                    }
                    //字节流读取
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);   // 把自己字节序列恢复成Java对象

                }catch (IOException e){
                    throw new ClassNotFoundException(name);
                }
            }
        };
        //使用myloader类加载去加载名为JvmTest.Nine的类,并实例化对象obj
        Object obj = myLoader.loadClass("JvmTest.Nine").newInstance();

        System.out.println(obj.getClass()); //对象obj的确是类JvmTest.Nine实例化的对象
     //instanceof Java中的一个双目运算符,用来测试一个对象是否为一个类的实例
System.out.println(obj instanceof JvmTest.Nine); //所属类检查,判断obj是否属于类 } }
class JvmTest.Nine
false

上述代码重写了一个类加载器,使用这个类加载器去加载一个名为JvmTest.Nine的类,并创建了一个对象obj。结果发现obj的确是JvmTest.Nine的一个实例,但是做对象所属类检查的时候,却输出false。原因如下:

因为虚拟机出现了两个JvmTest.Nine类,一个是系统应用程序类加载器加载的,另一个是自定义myLoader类加载器加载的。虽然都来自同一个Class文件,但确实不同的独立的类。再次验证那句话:

即使两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那么这两个类就不相等。

 

 三、双亲委派模型

从Java虚拟机的角度来讲,只存在两种不同的类加载器:

  1. 启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分
  2. 除了启动类加载器的所有其他类加载器,这些类加载器由Java语言实现,独立于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader。

类加载器可以划分得更细致一些,主要分为以下三种:

  1. 启动类加载器(Bootstrap ClassLoader),最顶层的类加载器,由C++实现,无法被Java程序直接引用。负责加载<JAVA_HOME>\lib目录下的jar包的类或者被-Xbootclasspath参数所指定的路径中的所有类。
  2. 扩展类加载器(Extension ClassLoader),主要负责加载<JAVA_HOME>\lib\ext目录下的jar包和类,或被java.ext.dirs系统变量所指定的路径中所有类库,开发者是可以直接使用的。
  3. 应用程序类加载器(Application ClassLoader),面向我们用户的加载器,负责加载当前应用classpath(用户类路径)下的所有jar包和类。应用程序类加载器也称为系统类加载器。

 

类加载器的双亲委派模型

每一个类都有一个对应它的类加载器。系统中的ClassLoader在协同工作的时候会默认使用双亲委派模型:在类加载的时候,系统会首先判断当前类是否被加载过,已经被加载的类会直接返回,否则才会尝试加载。首先会把该请求委派父类加载器的loadClass()处理,因此所有的请求最终都应该传送到顶层的启动类加载器BootstrapClassLoader中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器BootstrapClassLoader作为父类加载器。流程图如下所示:

技术分享图片

 

 

 

 

 

 

 

 

 

 

 

 

                        

 

类加载器

原文:https://www.cnblogs.com/xiazhenbin/p/14100069.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!