java类加载器

来源:互联网 发布:淘宝打折软件在哪里 编辑:程序博客网 时间:2024/06/04 19:25

1,基础

类加载器树:
这里写图片描述

  • 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
  • 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
  • 自定义类加载器:开发人员可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。

类加载流程

关键字:代理。
先交给父加载器加载。
知识点:jvm怎么判断两个类是相同的?
类的全名+是否由同一个类加载器加载。同样的字节码被不同的类加载器加载,是不同的。所以有时候,你明明看到两个类是相同的类名,但却报ClassCastException。可能就是类加载器不同的原因。

明白了这点,就明白了为什么类加载流程要使用父类代理。就是为了加载同一份java核心类库,保证安全。
另外不同的类加载器为相同名称的类创建了额外的名称空间。相同名称的类可以并存在 Java 虚拟机中,只需要用不同的类加载器来加载它们即可。不同类加载器加载的类之间是不兼容的,这就相当于在 Java 虚拟机内部创建了一个个相互隔离的 Java 类空间。这种技术在许多框架中都被用到,后面会详细介绍。

因为这种代理模式,所以真正完成类加载的类加载器和启动加载的类加载器可能不是同一个。真正完成类的加载工作是通过调用 defineClass来实现的;而启动类的加载过程是通过调用 loadClass来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。一个类的定义加载器是它引用的其它类的初始加载器。

方法 loadClass()抛出的是 java.lang.ClassNotFoundException异常;方法 defineClass()抛出的是 java.lang.NoClassDefFoundError异常。

类加载器在成功加载某个类之后,会把得到的 java.lang.Class类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass方法不会被重复调用。

Class.forName

Class.forName也可以用来加载类。
用法:

Class.forName(name, initialize, loader)Class.forName(className)

第一种形式的参数 name表示的是类的全名;initialize表示是否初始化类;loader表示加载时使用的类加载器。第二种形式则相当于设置了参数 initialize的值为 true,loader的值为当前类的类加载器。
拿到类就可以newInstance()了

0 0
原创粉丝点击