动态获取当前行号

2022-09-01 06:26:44

在Java中,有没有办法通过反射或一些很棒的API来动态获取当前的行号?就像发生异常时一样,行号在堆栈跟踪中打印出来,如下所示:

at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:348)

现在有没有办法像下面的代码一样打印或记录?

log.error("Error in: " + this.getClass.getName() + "at line #"+ this.getClass.getActualLine());

你可能会问,我为什么不直接打印行号?好吧,因为代码可能会被删除或添加到特定的log.error()方法调用之前。


答案 1

您可以创建一个可抛出的,并使用它的 StackTraceElements

  System.err.println(new Throwable().getStackTrace()[0].getLineNumber());

正如@Joachim所说,你也可以使用Thread.getStackTrace(),例如

  System.err.println(Thread.currentThread().getStackTrace()[1].getLineNumber());

请注意,第二种方法返回一个稍微不同的数组 - 您需要使用索引为 1 的 array 元素来获取当前行号,因为它包含对自身的调用作为第一个元素。getStackTrace()

另请注意@Joachim的答案中有关日志记录和性能的注释。


答案 2

首先:如果有的话,那么日志记录模式(或布局器,或者您的日志记录框架调用该部分的任何内容)应该执行此操作。代码中的记录器调用应写入实际的业务信息。记录器应添加有关位置的信息。

下一步:获得这种操作是昂贵的(就时间而言),因为Java没有为此进行优化。在运行时,JVM 需要检查其状态,加载/解析调试信息并找到与给定指令对应的行号。这就是为什么这种信息通常只是在发生异常时给出的原因(在这种情况下,我们已经遇到了问题,并且知道花费的时间通常是值得的)。

最后但并非最不重要的一点是:如果出于某种原因,您自己需要该信息,则可以使用Thread.getStackTrace()并检查其上的第二个StackTraceElement