我可以从jar成功加载其他类的类的ClassNotFoundException

时间:2012-02-03 17:41:17

标签: java ruby classloader

背景
我正在尝试在Java类中启动嵌入式Tomcat服务器,通过JRuby从Ruby脚本启动。这意味着我使用的所有jar都需要从ruby脚本加载。

在红宝石剧本中我有:

require 'java'
load 'servlet-api-2.5.jar'
...
com.mycompany.RunWebApplicationTomcat.main(nil)
//com.mycompany.RunWebApplicationJetty.main(nil)  //Commented out for Tomcat Test

Java类如下:

   public class RunWebApplicationTomcat {

    public static void main(String[] args) throws Exception {

          try {
              Class.forName("javax.servlet.http.HttpServlet");
          } catch(ClassNotFoundException e) {
              System.err.println(e.getMessage());
          }

          DispatcherServlet dispatcherServlet =  new DispatcherServlet();
              ....
        }
   }

问题:
当我运行脚本时,我在Class.forName测试中没有异常,但是当尝试DispatcherServlet初始化时,我在javax.servlet.http.HttpServlet 上得到了一个 ClassNotFoundException。 (DispatcherServlet是spring servlet,但我尝试过其他servlet实现并遇到同样的异常)

为什么我99.9%确定servlet-api.jar在类路径中:
这真的很奇怪,我已经使用相同的模式成功创建了一个Embedded Jetty服务器。该服务器不需要HttpServlet类。但是它确实使用了HttpServletRequest / Response类,它们位于相同的servlet-api.jar中,并且运行正常。

问题:
1.有没有人知道如何无法找到加载到类路径中的jar中的某个特定类? 2.是否有一些Java安全机制可以阻止实例化类? (JRuby可执行文件是一个自定义的,专有的黑盒子,所以我不确定那里会发生什么)
3.我可能会进行任何其他可以解决问题的测试吗?

堆栈跟踪

Caused by: java.lang.NoClassDefFoundError: javax/servlet/http/HttpServlet
    ... 38 more
Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

2 个答案:

答案 0 :(得分:2)

ClassNotFoundException可能由许多因素引起,包括:

  • 有问题的课程不在那里。

  • 这个类在那里,但它所依赖的其他一些类/接口/注释/枚举不存在。

  • 您的课程取决于以前在课堂初始化时失败的其他课程。

证据似乎与所有这些相矛盾。 (根据javadoc,Class.forName(String)触发类初始化。)但是,堆栈跟踪会提供更多证据。


这里的类加载器可能会有些棘手;即DispatcherServlet类之前已使用不同的类加载器加载到forName正在使用的“当前”类加载器。

您还应该考虑forName在示例代码中抛出您未测试的其他Exception(或Error)的可能性。

答案 1 :(得分:0)

Tomcat提供自己版本的servlet-api.jar。版本的差异可能会导致缺少类。

来自Tomcat 7.0 Docs

  

最后,类加载器将显式忽略包含Servlet API类的任何JAR文件 - 不要在Web应用程序中包含此类JAR。