1. ホーム
  2. java

log4jが例外のためにスタックトレースを表示しない

2023-11-02 16:50:53

質問

tomcatでlog4jを使用しています。JSPやサーブレットで例外をログに記録する場合、どのようにすればよいでしょうか。

private Logger _log = Logger.getLogger(this.getClass());
...
try{...} catch (Exception e) {
    _log.error("Error refreshing all prices", e);
}

スタックトレースなしで、例外の1行目だけが表示されます。

17-Feb 17:37:45 ERROR AutoContrib:175 - csv ファイルを公開中に例外が発生しました。 java.lang.ArrayIndexOutOfBoundsException を発生させました。

全く役に立ちません!

私のlog4j.propertiesファイル(/tomcat/common/classes/log4j.properties)は、以下のような感じです。

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.stdout.threshold=info

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.maxFileSize=5000KB
log4j.appender.file.maxBackupIndex=10
log4j.appender.file.File=${catalina.home}/logs/web.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.file.threshold=info

log4j.rootLogger=debug, stdout, file

どのように解決するのですか?

実際には、ホットスポットの最適化が原因でしょう。同じ例外がある回数投げられると、トレースの印刷を停止します。これは VM arg でオフにすることができます。

以下から http://www.oracle.com/technetwork/java/javase/relnotes-139183.html :

サーバー VM のコンパイラーは、すべての "cold" の組み込み例外に対して、正しいスタックバックトレースを提供するようになりました。 コールド例外を提供するようになりました。パフォーマンス上の理由から このような例外が数回スローされた場合、メソッドは再コンパイルされることがあります。 再コンパイル後、コンパイラは、より高速な戦術として 再コンパイル後、コンパイラはスタック・トレースを提供しない事前割り当て例外を使用したより高速な戦術を選ぶかもしれません。事前割り当て例外の使用を 事前割り当て例外の使用を完全に無効にするには、この新しいフラグを使用します。 -XX:-OmitStackTraceInFastThrowを使用します。

詳細はこちら。

http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/