Java中所有的类都是由classloader进行加载的。
通常情况下我们不需要显式的去使用类加载器。
但是对于一个web容器而言,通常拥有多个classloader,我们知道,每个classloader所加载的类彼此都是不可见的。比如一个servlet程序,它使用了WEB-INF/lib下面的log4j,而tomcat本身也有一套logj的包。显然对于servlet而言,它是看不到tomcat的log4j,反之亦然。
这一点如何做到?
答案就是线程自身的contextClassLoader。我们知道java代码总是在某个线程中执行的,这个线程所需要的类,则是由它自己的contextClassLoader所加载;当一个线程开启了一个子线程,则子线程会隐式的继承父线程的classloader。这个就是类加载器隔离的关键。
我们可以很容易写一小段代码来证实:
下面这段代码运行后输出是,
main_cl:sun.misc.Launcher$AppClassLoader@1a46e30
MainProc:org.kevx.MyClassLoader@1fb8ee3
SubProc:org.kevx.MyClassLoader@1fb8ee3
证明了上面这个结论。
- class MainProc implements Runnable {
- @Override
- public void run() {
- out.println( "MainProc:" + Thread.currentThread().getContextClassLoader());
- new Thread( new SubProc()).start();
- }
- }
- class SubProc implements Runnable {
- @Override
- public void run() {
- out.println( "SubProc:" + Thread.currentThread().getContextClassLoader());
- }
- }
- class MyClassLoader extends URLClassLoader {
- public MyClassLoader(URL[] urls) {
- super(urls);
- }
- }
- public class AsciiUtil {
- public static void main(String[] args) throws Exception {
- out.println( "main_cl:" + Thread.currentThread().getContextClassLoader());
- URL url = new URL( "file:///c:/Program Files/Java/jre6/lib" );
- MyClassLoader mcl = new MyClassLoader( new URL[]{url});
- Thread. currentThread().setContextClassLoader(mcl);
- new Thread( new MainProc()).start();
- }
- }
转载于:https://blog.51cto.com/spinlock/943735