Tomcat自定义类装入器装入一些jar文件失败



我有一个web应用程序,它有一个上传功能,包括上传一个包含java应用程序的包(它可能包含多个依赖项)

为此,对于每个上传的应用程序,我将创建一个自定义类加载器来动态加载应用程序的类路径。解决方案是工作良好,直到我得到这个错误时,上传一个新的应用程序:

javax.xml.stream.FactoryConfigurationError: Error creating stream factory: java.lang.ClassNotFoundException: de.odysseus.staxon.json.stream.impl.JsonStreamFactoryImpl

我已经验证了我上传的包包含axon,并且还验证了我的自定义类加载器可以加载该类:

Object a=Class.forName("de.odysseus.staxon.json.stream.impl.JsonStreamFactoryImpl",true , classLoader).newInstance();

那么,为什么会有这个例外呢?

当您调用Class.forName(className, initialize, classLoader)时,您正在要求JVM使用该自定义类加载器加载类。如果不指定ClassLoader——例如只调用Class.forName(className),那么JVM将使用ClassLoader作为线程的"context ClassLoader"。每个线程都有其中一个,您的代码可以很容易地更改上下文类加载器。

如果你有一些导致类被加载的代码——像这样:

MyClass foo = new MyClass();

MyClass类将被ClassLoader加载,如果它还没有加载。在类还没有加载的情况下,不可能调用构造函数并提供ClassLoader来加载类。在本例中,线程的上下文ClassLoader是user。

此外,如果你调用了一些你无法控制的代码,那么这些代码可能会以多种方式导致其他类被加载,并且由于你无法控制这些代码,线程的上下文ClassLoader也将被使用。

那么,如何设置线程的上下文ClassLoader ?容易:

ClassLoader cl = Thread.currentThread().getContextClassLoader();
ClassLoader myClassLoader = ...; // You figure this out
try
{
    Thread.currentThread().setContextClassLoader(myClassLoader);
    // Do work that requires your ClassLoader to work
}
finally
{
    // Always restore the previous CCL after work is done
    Thread.currentThread().setContextClassLoader(cl);
}

你要做的另一件事是确保你的自定义ClassLoader将任何类加载请求委托给父ClassLoader。父ClassLoader应该是ClassLoader,如果你不试图使用自己的ClassLoader,那么自然会使用它。

所以,你可能想要这样的东西:

ClassLoader cl = Thread.currentThread().getContextClassLoader();
ClassLoader myClassLoader = new MyClassLoader(cl); // Try 'cl' before your custom class loading
try
{
    Thread.currentThread().setContextClassLoader(myClassLoader);
    // Do work that requires your ClassLoader to work
}
finally
{
    // Always restore the previous CCL after work is done
    Thread.currentThread().setContextClassLoader(cl);
}

您可以在以下几个参考文献中找到有关ClassLoader s,特别是TCCL的更多信息:

  • http://docs.oracle.com/javase/jndi/tutorial/beyond/misc/classloader.html
  • 线程's上下文类装入器与普通类装入器的区别
  • http://www.javaworld.com/article/2077344/core-java/find-a-way-out-of-the-classloader-maze.html(也参考了前面的参考)
  • http://njbartlett.name/2012/10/23/dreaded-thread-context-classloader.html

最新更新