上下文类加载器未挂钩

5

我正在尝试定义一个自定义的ClassLoader。

public class ExampleLoader extends ClassLoader
{
    public Class<?> findClass(String name) throws ClassNotFoundException
    {
        System.out.println("This never gets printed");
        return super.findClass(name);
    }

    public Class<?> loadClass(String name, boolean b)
        throws ClassNotFoundException
    {
        System.out.println("This never gets printed");
        return super.loadClass(name, b);
    }
}

当然,这是我用来测试它的代码:

而且当然,我的测试代码如下:

public class Tester
{
    public static void main(String[] args)
    {
        Thread t = new FooThread();
        t.setContextClassLoader(new ExampleLoader());
        t.start();
    }
}

class FooThread extends Thread
{
    public void run()
    {
        new RandomClass();
    }
}

问题在于我的代码中的行没有被打印出来。显然我漏掉了什么。
2个回答

6
这与 bug 4868493 有关。以下是相关的引用:

不幸的是,getContextClassLoadersetContextClassLoader的文档可能会让人得出提交者的代码应该按预期工作的结论。

然而,在类加载中有一个基本规则-没有任何类可以自动加载“下游”的类,即不能直接由该类的ClassLoader或其祖先之一的ClassLoader加载。

这在许多地方都有描述。例如,请思考可在此处获得的白皮书: http://www.javageeks.com/Papers/ClassForName/index.html以获得启示。

关键点似乎是Java语言不会自动使用上下文类加载器。它只是一个传统的地方,用于存储上下文类加载器,以便其他类可以使用 Class.forName 的3个参数形式

Thread.getContextClassLoaderThread.setContextClassLoader的规范应得到澄清,并且应澄清“上下文类加载器”的含义。重新分类为文档错误。

规范尚未得到澄清。

要使其最初想要的工作,请将new RandomClass()替换为

Class.forName(RandomClass.class.getName(), 
              true,
              getContextClassLoader()).newInstance();

这将打印出以下内容,似乎有些矛盾:
这永远不会被打印

出于好奇,像Tomcat这样的应用程序是如何实现的呢? 我的理解是所有的Tomcat Web应用都运行在共享的JVM中,但当它们使用类时,类定义来自它们各自的war文件。 你知道他们是如何实现这一点的吗? - Jim
2
他们使用 ClassLoader#loadClass()。通过这种方式,在线程中存储和传递ClassLoader实例。查看源代码的好起点是org.apache.catalina.core.DefaultInstanceManager - BalusC

0

通常情况下,JVM中的所有类加载器都按层次结构组织,每个类加载器(除了引导整个JVM的原始类加载器)都有一个单一的父级。当要求加载一个类时,每个符合规范的类加载器都应该首先委托其父级加载,并在父级失败后尝试定义该类。

在您的情况下也是同样的情况。"RandomClass"需要被加载,ContextClassLoader委托给其父级,以此类推。其中一个父类加载器能够加载"RandomClass"("RandomClass"在父类路径中)。因此,您的SOP没有显示出来。

参考以下文章,虽然有点旧但很好:

http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接