代码之家  ›  专栏  ›  技术社区  ›  omerkudat

没有调试代理,nullpointerException堆栈跟踪不可用

  •  58
  • omerkudat  · 技术社区  · 16 年前

    我最近发现了一个导致空指针异常的错误。使用标准SLF4J语句捕获并记录异常。以下简略代码:

    for(Action action : actions.getActions()) {
        try {
            context = action.execute(context);
        } catch (Exception e) {
            logger.error("...", e);
            break;
        }
    }
    

    如你所见,没什么好奇心。但是,在我们拥有的所有异常日志记录语句中,只有这一条语句不打印堆栈跟踪。它所打印的全部是消息(表示为“…”)和异常类的名称(Java.Lang.NulLoPoExtExtExchange)。

    由于异常上的堆栈跟踪是延迟加载的,所以我认为可能存在某种类型的指令重新排序问题,并决定在LOG语句之前调用e.getStackTrace()。这没什么区别。

    所以我决定在启用调试代理的情况下重新启动。但是,因为我甚至附加了这个过程,我注意到现在堆栈跟踪正在打印。所以很明显,调试代理的存在导致了一些额外的调试信息变得可用。

    从那以后,我已经修复了异常的根本原因。但我想了解一下没有调试器堆栈跟踪为什么不可用。有人知道吗?

    澄清: 这不是日志记录问题 . 想象一下相同的try/catch子句,但在catch中,我打印了以下值:

    e.getStackTrace().length
    

    如果没有调试程序,它将打印“0”,如果使用调试程序,它将打印一个正数(在本例中为9)。

    更多信息:这发生在JDK 1.6.0 bit、AMD64、Linux 2.6.9上。

    3 回复  |  直到 14 年前
        1
  •  19
  •   Nick Fortescue    16 年前

    此代码是否可能在内部循环中?然后,JIT编译器可能会将此调用堆栈编译为本机代码,从而丢失堆栈信息。然后,当附加调试器时,它将禁用JIT,使信息再次可用。

    其他的手动异常会继续显示信息,因为JIT没有优化。

    在第102行,这个类源代码的注释中的其他人可能会遇到这种情况:

    http://logging.apache.org/log4j/1.2/xref/org/apache/log4j/spi/LocationInfo.html

        2
  •  88
  •   Daniel    14 年前

    使用jvm标志-xx:-omitstacktraceinfastthrow,您可以为此用例禁用jvm的性能优化。如果给定此参数(禁用标志),StackTrace将可用。

    有关更多信息,请查看以下发行说明:

    服务器vm中的编译器现在为所有“冷”内置异常提供了正确的堆栈回溯。出于性能目的,当这种异常被抛出几次时,可以重新编译该方法。重新编译后,编译器可以使用不提供堆栈跟踪的预分配异常选择更快的策略。要完全禁用预分配异常的使用,请使用此新标志:-xx:-omitstacktraceinfastthrow。“ http://java.sun.com/j2se/1.5.0/relnotes.html

        3
  •  0
  •   seth    16 年前

    我可以复制这个,但这似乎有点奇怪,这会发生在你的行动某处。

    如果使用空数组调用setstacktrace,那么只会显示文本。

     public class Fark {
       public static void main(String[] args) {
           try {
               Fark.throwMe(args.length != 0);
    
           }
           catch (Exception e) {
               e.printStackTrace();
           }
    
       }
    
         public static final void throwMe(boolean arg) throws Exception{
             Exception e = new NullPointerException();
             if (arg) {
               e.setStackTrace(new StackTraceElement[0]);
             }
             throw e;
         }
     }
    

    运行它…

    % java Fark
    java.lang.NullPointerException
            at Fark.throwMe(Fark.java:15)
            at Fark.main(Fark.java:5)
    
    % java Fark nothing
    java.lang.NullPointerException