目录
Java 虚拟机对 class 文件采用的是按需加载的方式(也可以称之为懒加载),也就是说当 需要使用该类时才会将它的 class 文件加载到内存生成 class 对象。而且加载某个类的 class 文件时,Java 虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任 务委派模式(类似带孩子)。
基于双薪委派模型进行类的加载,其具体过程如下:
1.1:
如果一个类加载器收到了类加载请求时,它并不会自己先去加载,而是把这个请求委
托给父类的加载器去执行;
1.2:
如果父类加载器还存在其父类加载器,则进一步向上询问,依次递归,请求最终将
到达顶层的启动类加载器(使用
C/C++
去实现的类加载器);
1.3:
如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加
载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
1.4:
父类加载器一层一层往下分配任务,如果子类加载器能加载,则加载此类,如果将
加载任务分配至系统类加载器也无法加载此类,则抛出异常。
2.2:双亲委派模型优缺点
优点:
采用双亲委派模式可以保证类型加载的安全性,不管是哪个加载器加载这个类,最终都是委托给顶层的BootstrapClassLoader来加载的,只有父类无法加载自己才会尝试加载,这样就可以保证任何的类加载器最终得到的都是同样一个Object对象
注:(同一个加载器加载同一个类 得到的对象一定相等 )
缺点:
在双亲委派模型中,子类加载器依旧可以使用父类加载器加载已经加载过的类,而父类加载器却无法使用子类加载器加载已经加载过的类。这就导致了双亲委派模型并不能解决所有的类加载器问题
注:(如A类已经有一个classA 恰好B类也有一个clasA 但是两者内容不一致 不打破双亲委派模型 只会加载一次)
1.1:实现类的动态加载
自定义类加载器继承
ClassLoader
,然后重写
ClassLoader
中的
loadClass
方法,并采用
自己定义的类机制对类进行加载实现。
代码如下所示
package
com.java.jvm.loader
;
import
java.io.
*;
/**
* ClassLoader
没有抽象方法为什么还要将此类定义为抽象类?外界不允许直接构建此
类对象
*/
public class
BreakDoubleParentAppClassLoader
extends
ClassLoader
{
private
String
baseDir
;
public
BreakDoubleParentAppClassLoader
(
String
baseDir) {
this
.
baseDir
= baseDir;
}
/**
*
重写
loadClass
方法,打破双亲委派模型
* @param
name
* @return
* @throws
ClassNotFoundException
*/
@Override
public
Class
<?>
loadClass
(
String
name)
throws
ClassNotFoundException
{
try
{
//
我们自己先去加载,加载不了
(
例如
java.lang.Object)
则抛出异常
return
findClass(name);
}
catch
(
Exception
e){
//
自己加载不了,再交给
parent
加载器对加载
return super
.loadClass(name);
}
}