JVM - 类加载器
作用:负责将 class 加载进入 JVM 中,审查每个类由谁加载。对于用户而言,最大的好处是实现类的动态加载操作。
产生原因:由于 class 类提供的 forName()
方法只能加载 .CLASSPATH
中的类,而类的加载路径则有可能在网络、文件、数据库中,因此需要类加载器
获取:通过调用 Class 类中的 getClassLoader( )
方法即可获取一个 ClassLoader
分类
一、虚拟机自带的加载器
启动类加载器(Bootstrap ClassLoader):由 C++ 编写,引擎加载器(核心加载器),负责加载核心 JAVA 类(即所有 java.*开头的类)。如
java.lang
中的类。扩展类加载器(Extension ClassLoader):由 Java 编写,负责加载在拓展库下的类——拓展的 JAVA 类 和 第三方程序类库。(例如所有 javax.*开头的类和存放在 JRE 的 ext 目录下的类)
应用程序类加载器(Application ClassLoader):也叫系统类加载器,由 Java 编写,加载应用程序自身的类(即程序猿编写的类),如当前应用中
CLASSPATH
中的所有类
上面这三个加载器是一个继承关系:AppClassLoader->Extension->Bootstrap(->代表继承)
二、用户自定义加载器
java.lang.ClassLoader
的子类,用户可以定制类的加载方式。
产生的原因:
一方面是由于 java 代码很容易被反编译,如果需要对自己的代码加密的话,可以对编译后的代码进行加密,然后再通过实现自己的自定义类加载器进行解密,最后再加载。
另一方面也有可能从非标准的来源加载代码,比如从网络来源,那就需要自己实现一个类加载器,从指定源进行加载。
双亲委派机制
定义
某个特定的类加载器在接到加载类的请求时
首先将加载任务委托给父类,依次递归
如果父类加载器可以完成类加载的任务,就成功返回
只有父类加载器都无法完成加载任务时,才自己去加载。
比如,当加载一个 Person.class 的时候,加载这个类的请求会由 Application 类加载器委托给它的父类加载器 Extension 类加载器,然后 Extension 类加载器会将请求委托给 Bootstrap 类加载器,Bootstrap 类加载器会在 rt.jar 包中检查是否有这个类,如果有则返回,如果没有则将请求返回给 Extension 类加载器,Extension 类加载器会查看
jre/lib/ext
这个目录,如果没有,则返回给 Application 类加载器,Application 类加载器会在当前项目的 classpath 中进行寻找,如果没找到,则会抛出异常。
原因:为了保证 java 的沙箱机制,通过这种方式,会优先使用 Java 自身的类,这样可以防止恶意代码对 Java 的破坏,如通过编写常用类的同名类,来骗过程序员,由此来获取一些私密数据。
评论