Java虚拟机--类加载器

类加载器

类加载器:类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何获取所需要的类,实现这个动作的代码模块成为“类加载器”。

类加载器分类:

(1)启动类加载器:负责将放在<JAVA_HOME>\lib目录中,并且是虚拟机识别的 类库加载到虚拟机内存中,启动类加载器无法被Java程序直接引用

(2)扩展类加载器:由sun.misc.Launcher$ExtClassLoader实现,负责加载 <JAVA_HOME>\lib\ext目录中类库,开发者可以直接使用扩展类加载器。

(3)应用程序类加载器:是ClassLoadergetSystemClassLoader()方法返回值,也 城系统类加载器,负责加载用户类路径(ClassPath)上指定类库,开发者可以直接 使用,如果没有定义过自己的类加载器,一般下这个就是程序默认类加载器。

类加载机制:

全盘负责:当一个类加载器负责某个Class时,该Class所依赖和引用的Class也由该加载 器负责载入,除非显示使用另外一个加载器。

双亲委派:先让父类加载器试图加载目标类,只有在父类加载器无法加载该类的时候才尝 试自己去加载。

缓存机制:保证所有被加载的Class会被缓存,当使用时,先从缓存里面搜寻,不存在时 才从新读取对应二进制数据,并转化为Class对象,将其缓存起来。

类加载器加载步骤:

(1)检测此Class是否载入过,如果有,直接返回Class

(2)如果父加载器不存在(parent是根加载器或者本身是根加载器),执行第4步;如果 父加载器存在,执行第3步。

(3)请求父加载器加载目标类,成功则返回Class对象;不成功执行第5步。

(4)请求使用根加载器加载目标类,成功则返回;否则抛出ClassNotFoundExcption异常。

(5)寻找Class文件,查找到从文件中加载,成功后返回Class对象;否则抛出异常。

父委托模型:

所谓父委托模型:一个类加载器收到类加载请求,首先不会自己尝试去加载,而是 把请求委派给父类加载器去完成,每一层的类加载器都如此,因此所有加载请求最终被传 送到顶层启动类加载器中,只有当夫加载器反馈自己无法完成这个加载请求时(搜索范围 中没有找到所需的类),子加载器才去尝试自己去加载。

父委托模型好处:提高java的安全性。比如:如果父加载器已经加载了某个类,那么自己 则不可以再加载该类,使得一些与java类库同名的类不能加载进来。

父委托模型实现代码

自定义类加载器:

JVM中除了根加载器之外都是ClassLoader子类实例,所以我们可以通过扩展ClassLoader 子类,重写其方法实现自定义的类加载器。

ClassLoader类关键方法:

loadClass(String name,boolean resolve):该方法ClassLoader的入口点,更加二进制名加载 类,系统就是调用ClassLoader方法来获取指定Class对象。

findClass(String name):根据二进制名字查找类。

defineClass(String name,byte[] b,int off, int len ):将指定类字节码文件读入数组,转化为 Class对象,字节码文件可以来源于文件、网络等;define管理JVM的许多复杂实现,复 杂将字节码分析称运行时数据结构,并校验有效性等;程序员无需复写该方法,也无法复 写(该方法为final型)。

实现自定义类加载器方法:

可以重写loadClass()方法挥着findClass()方法,推荐重写findClass()方法。

因为loadClass方法的执行步骤如下:

(1)调用findLoadedClass(String name)检查是否有加载类,如果已经加载直接返回。

(2)在父类加载器上调用loadClass方法,如果父类为null,使用跟加载器加载。

(3)调用findClass方法查找类

可以看出,重写findClass()方法可以避免覆盖类加载器的父类委托、缓冲机制两种策略, 如果重写loadClass方法,实现逻辑更为复杂。

自定义ClassLoader例子:

阅读更多
个人分类: Java虚拟机
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭