背景
我正在尝试在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)
答案 0 :(得分:2)
ClassNotFoundException
可能由许多因素引起,包括:
有问题的课程不在那里。
这个类在那里,但它所依赖的其他一些类/接口/注释/枚举不存在。
您的课程取决于以前在课堂初始化时失败的其他课程。
证据似乎与所有这些相矛盾。 (根据javadoc,Class.forName(String)
触发类初始化。)但是,堆栈跟踪会提供更多证据。
这里的类加载器可能会有些棘手;即DispatcherServlet类之前已使用不同的类加载器加载到forName
正在使用的“当前”类加载器。
您还应该考虑forName
在示例代码中抛出您未测试的其他Exception
(或Error
)的可能性。
答案 1 :(得分:0)
Tomcat提供自己版本的servlet-api.jar。版本的差异可能会导致缺少类。
最后,类加载器将显式忽略包含Servlet API类的任何JAR文件 - 不要在Web应用程序中包含此类JAR。