目前,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
注意,条目 line 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=>
有没有什么理由让构造函数调用位置不在行号表中有自己的条目?