目前,Clojure编译器并没有为构造函数调用位置生成行号表的条目,这与方法调用位置不同。
例如,假设你有如下代码
(ns example.core)
(defn f []
(StringBuilder.))
这段代码将生成如下的字节码和行号表
public static java.lang.Object invokeStatic();
descriptor: ()Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: new #13 // class java/lang/StringBuilder
3: dup
4: invokespecial #14 // Method java/lang/StringBuilder."<init>":()V
7: areturn
LineNumberTable:
line 3: 0
// line 4: 4 <- this entry should be here
注意条目 第4行:4
应该在行号表中,但实际上并没有。
实际上,我们可以确认编译器在 NewExpr
的 emit()
实现中完全没有调用 visitLineNumber
。
当你写一个可能显式抛出多个异常的函数时,这可能会成为一个真正的问题
(ns example.core)
(defn f [x]
(if (>= x 0)
(throw (IllegalArgumentException.))
(throw (ArithmeticException.))))
在这种情况下,异常抛出的堆栈跟踪将不会指示异常发生的确切位置
user=> (f 1)
Execution error (IllegalArgumentException) at example.core/f (core.clj:4).
null
user=> (pst)
IllegalArgumentException
example.core/f (core.clj:4) ;; <- should be "core.clj:5"
example.core/f (core.clj:3)
user/eval160 (NO_SOURCE_FILE:1)
...
nil
user=> (f -1)
Execution error (ArithmeticException) at example.core/f (core.clj:4).
null
user=> (pst)
ArithmeticException
example.core/f (core.clj:4) ;; <- should be "core.clj:6"
example.core/f (core.clj:3)
user/eval164 (NO_SOURCE_FILE:1)
...
nil
user=>
构造函数调用位置没有在行号表中拥有自有条目的原因是什么?