ClassLoader疑惑

这两天在读王森写的JAVA深度历险, 跟着书上作了点实验,现有一问题如下:

Test.java:
public class Test {
public static void main(String args[]) {
System.out.println(Test.class.getClassLoader());
Testlib tl = new Testlib();
tl.print();
}
}

Testlib.java:
public class Testlib {
public void print() {
System.out.println(
this.getClass().getClassLoader());
}
}
编译后目录如下:
<JRE所在目录>\classes下:
Test.class
<JRE所在目录>\lib\ext\classes下:
Test.class
Testlib.class
根据类装载机制,,当AppClassLoader要载入Test.class时,先请其parent, 也就是ExtClas
sLoader来载入, 而ExtClassLoader又请求其Parent, 即BootStrap Loader来载入Test.cl
ass, 由于<JRE所在目录>\classes目录为Bootstrap Loader的搜索路径之一,所以Bootstr
ap Loader找到了test.class,因此将它载入.接着在Test.class之内有载入Testlib.class的需求,由于Test.class
是由BootStrap Loader所载入,所以Testlib.class内定是由Bootstrap Loader根据其搜索
路径来寻找,但是因为Bootstrap Loader根本找不到Testlib.class, 而Bootstrap Loader
又没有parent, 所以无法载入Testlib.class. 故java Test后结果如下:
null
Exception in thread "main" java.lang.NoClassDefFoundError:Testlib at Test.main
<Test.java:6>
但我把Test代码中的Test.class.getClassLoader()变为Thread.currentThread().getCon
textClassLoader()后第一行输出变成了AppClassLoader, 请问这是为什么?我查过JDK文档
,上面写得很清楚:
The context ClassLoader is provided by the creator of the thread for use by code running in this thread when loading classes and resources. If not set, the default is the ClassLoader context of the parent Thread. The context ClassLoader of the primordial thread is typically set to the class loader used to load the application.
应该也是parent来load, 既然parent能找到,为什么这里是AppClassLoader来load?望指点

另外对于第一种情况,又没有什么办法能让Testlib.class被load?书上说是用Context Loader,不明白是何意

疏忽了,放class文件的根目录为 JRE所在目录

对于java类的classloader,当前线程的classloader不一定就等于当前某个类的classloader,但在某个类中调用加载其他类的时候,则一定是使用当前这个类的classloader加载的.
所以从现象上看到当前线程的classloader是
AppClassLoader,同时由于是在Test中加载Testlib此时使用了Test的classloader来加载.而test本身的classloader是Bootstrap Loader,它自然是找不到Testlib.至于为何当前线程的classloader是AppClassLoader,这应该和JAVA虚拟机的实现有关系吧,我猜是java启动的主线程自己设置的吧

那么怎样解决这个问题呢?也就是说有什么办法能够让textlib被load?JAVA深度历险上讲是用Context Loader,但比较复杂,就没讲,大虾能否指点一二?

我不知道你指的问题是什么?
如果是要加载testlib,可以考虑将classes下testlib.class和test.class放在一起。
如果说是想自己在test.class中动态加载testlib.那么你需要自己编写classloader,其实很简单只要继承classloader,然后只要实现加载到testlib.class的byte[]字节流,就可以使用classloader中的defineClass和resolveClass方法来实现动态加载了。对于classloader的具体编写到网络上搜索一把,一大堆好事者都有给出例子

Thanks a lot