0

我在具有静态初始化程序的 Tomcat 应用程序中有一个类。AnError被抛出到静态初始化程序中。

问题是Tomcat显示的错误消息不包括“原因”,即没有显示来自该错误的消息和堆栈跟踪。

我可以重现这样的问题:

public class BadInitClass
{
  static
  {
    if (System.currentTimeMillis() > 0)
      throw new Error("I need to see this message");
  }

  public void doSomething()
  {
    System.out.println("functionality here");
  }
}

现在,如果我从单元测试中调用这个类:

@Test
public void testStaticInit() throws Exception
{
  new BadInitClass().doSomething();
}

然后测试打印出堆栈跟踪和消息:

java.lang.Error: I need to see this message
at mypackage.BadInitClass.<clinit>(BadInitClass.java:8)
at mypackage.BadInitClassTest.testStaticInit(UOneUtilitiesTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

但是,如果我将相同的代码添加到我的 Servlet 中,则 Tomcat 不会打印消息,只有以下内容:

exception

javax.servlet.ServletException: Servlet.init() for servlet MyServlet threw exception
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Thread.java:662)

root cause

java.lang.NoClassDefFoundError: Could not initialize class mypackage.BadInitClass
    mypackage.[calling code here]
    datcon.webmail.utils.DispatchedHttpServlet.init(DispatchedHttpServlet.java:77)
    MyServlet.init(MyServlet.java:57)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Thread.java:662)

note The full stack trace of the root cause is available in the Apache Tomcat/6.0.37 logs.

我正在运行 Tomcat 6.0.37。

这是Tomcat中的错误吗?有什么解决方法吗?

我知道静态初始化程序通常不是一个好主意,但是我有一些使用它们的遗留代码,并且在没有底层错误消息和堆栈跟踪的情况下调试这些问题非常痛苦。

我注意到单元测试没有NoClassDefFoundError- 问题与 tomcat 使用的自定义 ClassLoader 有关吗?

4

3 回答 3

1

我注意到NoClassDefFoundError不允许内部异常:http ://docs.oracle.com/javase/7/docs/api/java/lang/NoClassDefFoundError.html

在这种情况下,如果不修补 Tomcat 的类加载器以抛出不同类型的异常,这可能无法修复?

于 2013-11-15T11:18:12.013 回答
0

明白了——问题是静态初始化程序的错误只是第一次抛出。访问该类的第二次和后续时间,NoClassDefFoundError抛出没有内部异常详细信息的 a:

此测试演示了该问题(与BadInitClass上面相同的“”)。

public void testStaticInit() throws Exception
{
  // First attempt: the underlying message is available:
  try {
    new BadInitClass().doSomething();
  } catch (Throwable t) {
    assertThat(t, instanceOf(Error.class));
    assertThat(
        getFullStackTraceWithCauses(t),
        containsString("I need to see this message"));
  }

  // Second attempt: a NoClassDefFoundError with no "cause":
  try {
    new BadInitClass().doSomething();
  } catch (Throwable t) {
    assertThat(t, instanceOf(NoClassDefFoundError.class));
    assertThat(
        getFullStackTraceWithCauses(t),
        not(containsString("I need to see this message")));
  }
}

private String getFullStackTraceWithCauses(Throwable t)
{
  StringWriter writer = new StringWriter();
  t.printStackTrace(new PrintWriter(writer));
  return writer.toString();
}

这与Tomcat无关。

于 2013-11-15T11:58:41.400 回答
-1

BadInitClass 类中有哪些导入?BadInitClass 中使用了一个 tomcat 找不到的类。

于 2013-11-15T11:16:43.167 回答