読者です 読者をやめる 読者になる 読者になる

この日記は私的なものであり所属会社の見解とは無関係です。 GitHub: takahashikzn

Tomcat7のスタックトレースがちょっと便利

Java

2012-12-11追記: Tomcatの機能ではなくて、JDK7からそうなっているようです。失礼しました。



Tomcat7のスタックトレースがちょっと便利になっているということに気が付きました。
クラスがどのJarからロードされたか、わかるようになっています。([jasper.jar:7.0.11]という部分がそれ)

6:18:48,135 WARN  [Include] "http-bio-8080"-exec-3 - Exception thrown during include of /WEB-INF/template/outline-layout.jsp
org.apache.jasper.JasperException: java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Set
	at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:570) [jasper.jar:7.0.11]
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:457) [jasper.jar:7.0.11]
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:391) [jasper.jar:7.0.11]
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334) [jasper.jar:7.0.11]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) [servlet-api.jar:na]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) [catalina.jar:7.0.11]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [catalina.jar:7.0.11]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684) [catalina.jar:7.0.11]
	at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:593) [catalina.jar:7.0.11]
	at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:530) [catalina.jar:7.0.11]
	at org.apache.struts2.components.Include.include(Include.java:254) [struts2-core-2.2.1.1.jar:2.2.1.1]
	at org.apache.struts2.components.Include.end(Include.java:166) [struts2-core-2.2.1.1.jar:2.2.1.1]
    ...

近頃のJavaEEにおける開発では、本当に様々なライブラリを使う必要があります。
そして、ライブラリ自身も複雑な依存関係を持っています。

このように、とあるクラスがどのJarからロードされたのかわかるようになると、
トラブルシューティングの苦痛が少し和らぎます。たぶん。

ところで

『とあるクラスがどこからロードされたのか?』を調べたい時、
僕はいつもこうします。

String fooFQCN = Foo.class.getName();
String fooClassResourceName = "/" + fooFQCN.replace('.', '/') + ".class";

System.out.println(Object.class.getResource(fooClassResourceName));

クラスファイルをリソースとみなして、ファイルパスを取得するわけです。