电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

ClassLoader介绍


发布日期:2022/9/18
 

JVM在运行时会产生三个ClassLoaderBootstrap ClassLoaderExtension ClassLoader和AppClassLoader其中Bootstrap是用C++编写的我们在Java中看不到它是null它用来加载核心类库在JVM源代码中这样写道

static const char classpathFormat[] =

%/lib/rtjar:

%/lib/injar:

%/lib/sunrsasignjar:

%/lib/jssejar:

%/lib/jcejar:

%/lib/charsetsjar:

%/classes;

知道为什么不需要在classpath中加载这些类了吧?人家在JVM启动的时候就自动加载了并且在运行过程中根本不能修改Bootstrap加载路径

Extension ClassLoader用来加载扩展类即/lib/ext中的类

最后AppClassLoader才是加载Classpath的

ClassLoader加载类用的是委托模型即先让Parent类(而不是Super不是继承关系)寻找Parent找不到才自己找看来ClassLoader还是蛮孝顺的三者的关系为:AppClassLoader的Parent是ExtClassLoader而ExtClassLoader的Parent为Bootstrap ClassLoader加载一个类时首先BootStrap先进行寻找找不到再由ExtClassLoader寻找最后才是AppClassLoader

为什么要设计的这么复杂呢?其中一个重要原因就是安全性比如在Applet中如果编写了一个javalangString类并具有破坏性假如不采用这种委托机制就会将这个具有破坏性的String加载到了用户机器上导致破坏用户安全但采用这种委托机制则不会出现这种情况因为要加载javalangString类时系统最终会由Bootstrap进行加载这个具有破坏性的String永远没有机会加载

我们来看这段代码

[code]//Ajava

public class A{

public static void main(String[] args){

A a=new A();

Systemoutprintln(SystemgetProperty(javaextdirs));

Systemoutprintln(agetClass()getClassLoader());

B b=new B();

bprint();

}

}

//Bjava

public class B{

public void print(){

Systemoutprintln(thisgetClass()getClassLoader());

}

}[/code]

我们将它放在Classpath中则打印出

sunmiscLauncher$AppClassLoader@ec

sunmiscLauncher$AppClassLoader@ec

可见都是由AppClassLoader来加载的

我们将其放在%jre%/lib/ext/classes(即ExtClassLoader的加载目录其加载/lib/ext中的jar文件或者子目录classes中的class文件)中则会打印出

sunmiscLauncher$ExtClassLoader

sunmiscLauncher$ExtClassLoader

我们将Aclass放到%jre%/lib/ext/classes中而将Bclass放到classpaht中又会怎么样呢?结果是

sunmiscLauncher$ExtClassLoader

Exception in thread main javalangNoClassDefFoundError:B

at Amain(Ajava:)

怎么会这样呢?这其中有一个重要的问题A类当然是由ExtClassLoader来加载的B类要由哪个加载呢?B类要由调用它自己的类的类加载器(真拗口)也就是说A调用了B所以B由A的类加载器ExtClassLoader来加载ExtClassLoader根据委托机制先拜托Bootstrap加载Bootstrap没有找到然后它再自己寻找B类还是没找到所以抛出异常ExtClassLoader不会请求AppClassLoader来加载!你可能会想这算什么问题我把两个类放到一起不就行了?

呵呵没这么简单比如JDBC是核心类库而各个数据库的JDBC驱动则是扩展类库或在classpath中定义的所以JDBC由Bootstrap ClassLoader加载而驱动要由AppClassLoader加载等等问题来了Bootstrap不会请求AppClassLoader加载类啊那么他们怎么实现的呢?我就涉及到一个Context ClassLoader的问题调用ThreadgetContextClassLoader

上一篇:数组及循环的运用和甜饼Cookie的味道

下一篇:不使用function计算给定两个日期之间的工作日个数