java类加载器

类加载器,是用来加载Java类到Java虚拟机中。一般来说,Java虚拟机使用Java类的方式如下: .java->编译->.class->类加载器读取字节码->转换成类的实例->通过此实例的newInstance()方法创建该类的对象。
当然,也可能是你的.class文件来自于动态生成的,或者网络下载的。
 
基本上所有的Class Loader都是java.lang.ClassLoader类的一个实例。而ClassLoader就是负责根据一个指定的类名称,找到或者生活对应字节码,然后从这些字节码中生成一个java类,即java.lang.Class类的一个实例。当然该类还负责加载Java应用所需的资源如图像文件,配置文件等。

类加载器的组织结构:
类加载器大致分为两种,一种是系统提供的,一种是开发人员自己编写的。
而系统提供的主要有:
  • 引导类加载器(bootstrap class loader):用来加载Java核心库,他采用原生代码实现,并不继承自CLassLoader。
  • 扩展类加载器(extensions class loader): 用来加载Java扩展库,也就是lib/ext包。
  • 系统类加载器(system class loader): 根据应用程序的classpath来加载类,java应用程序类都是由他完成加载的,可以通过ClassLoader.getSystemClassLoader()得到她。
而开发人员自己的类加载器就需要通过继承ClassLoader来重写,以满足一些特殊的需求。
 
类加载器的组织结构类似一个树结构,分层的,根节点是 引导类加载器
 
类加载器的代理模式
类加载器在尝试自己去超找某个类的字节码并定义它的时候,会先代理给其父加载器,由父加载器先去尝试加载这个类,一次类推。
 
那么他为什么要这么做的,使用代理模式?
首先我们要先理解JVM是如何判断2个类相同的。JVM要检查类全名是否相同并且是否同一个类加载器加载。只有都相同,才认为相同。即便是同样的字节码,被不同的类加载器加载,也是不同的。
所以使用代理模式,可以保证Java核心类库的安全。举个例子:所有类都是集成自Object,而Object是引导类加载器负责完成,而如果开发者自己定义了这个类,并加载了,从而存在多个版本的Object。那么势必会造成这些类的子类之间的兼容问题。
 
另外还需要注意的是,不同的类加载器为相同名称的类创建了一个额外的名称空间。相同名称的类可以并在在JVM中,只需用不同的类加载器完成加载即可。不同类加载器加载的类是不兼容的,也就是相当于JVM内部创建了一个相互隔离的Java类空间
 
加载类的过程
前面说到,类加载器会首先代理给其他类加载器来尝试完成 加载某个类。这就意味着真正完成加载工作和 启动这个加载过程的类加载器可能不是同一个。简言之就是:加载由其他类加载器完成,启动由自己的类加载器启动。
真正完成类加载工作是通过调用defineClass来实现的;而启动类的加载过程是通过调用loadClass()来实现。
defineClass称为类的定义加载器,会抛出NoClassDefFoundError
loadClass称为类的初始加载器,会抛出ClassNotFoundException
 
JVM判断两个类是否相同的时候,就是使用类的定义加载器。也就是说哪个class loader启动这个类并不重要,重要的是由谁负责定义这个类。
那么,两个加载器的联系是什么呢? 一个类的定义加载器是引用其他类的初始加载器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值