我正在寻找一种方法,在输出的消息中包含__LINE__
作为编译时常量。
似乎存在各种解决方案,但__LINE__
in JS和__LINE__
in C#中建议的运行时损失很大。它们通常始终基于运行时对象StackFrame
作为log4j。
使用log4j在所需的基础上启用/禁用的可能性也不是一个选项,因为通常在发生错误时,启用行号为时已晚,并且内联代码似乎没有任何行号更多。 。是否有可能:
<子> 1。实际上我确实使用了一个丑陋的黑客:通过ANT技巧在构建服务器上结账后调用自定义预处理器
答案 0 :(得分:13)
在编译时发生的__LINE__
不可能产生效果。
您可以通过在运行时调用这样的函数来获取行号,
public static int lineNumber() {
return Thread.currentThread().getStackTrace()[2].getLineNumber();
}
答案 1 :(得分:9)
如果使用debug=line
选项进行编译,则行信息中存在行信息,但VM可以在运行时将其丢弃。这取决于您在启动Java程序时可以指定的一些选项。通常,使用调试信息运行的性能损失约为5%,加上perm gen空间中的更多内存。由于这些信息非常宝贵,我认为没有理由删除这些信息。
您的评论(Util.java(Inlined Compiled Code)
)表明您正在使用积极优化。如果可以,请关闭它们。这样,你可以简单地说:
// For Java 1.4, use new Exception().getStackTrace()
int line = Thread.currentThread().getStackTrace()[0].getLineNumber();
当您需要时(例如catch
或if (log.isInfoEnabled())
内)。
至于__LINE__
,Java编译器不支持这一点。您唯一的选择是使用一些黑客来过滤源。我建议在某处定义变量int __LINE__
并在需要时将其设置为某个随机值(0足够随机)。然后编写一个过滤器,用当前行号替换__LINE__ = \d+
中的数字。这样可以固定行号。
答案 2 :(得分:6)
我发现如果你正在寻找“到这里,到达这里”类型记录,这个课程会让事情变得简单。我有一个文件Here.java,我添加到我的项目中,它只包含以下类定义:
public class Here {
public static String at () {
StackTraceElement ste = Thread.currentThread().getStackTrace()[3];
String where = ste.getClassName() + " " + ste.getMethodName() + " " + ste.getLineNumber() + " ";
return where;
}
}
以最简单的形式使用它:
Log.v(TAG, Here.At());
或者,如果你想看到其他东西:
Log.v(TAG, Here.At() + String.format("interesting value = %d", my_val));
这将在第一种情况下给出“com.otherpackagenamestuff.MyClass myMethod 225”,并且相同但在第二种情况下附加“有趣值= 123”。
答案 3 :(得分:5)
开箱即用,这些宏不可用。 但是,使用检测和调试信息可以实现它。 检查http://www.gallot.be/?p=85
答案 4 :(得分:1)
我会使用一个日志框架,让它处理凌乱的细节。 java.util.logging和logback都可以轻松地显示有关调用者的信息,类似于 LINE 可以提供的信息。
主要好处是只在必要时才计算信息,因此不输出意味着没有开销。
答案 5 :(得分:0)
开箱即用,我认为Java并不能满足您的需求。
但是,如果您要编写自己的注释处理器并使用Java 6.0 compiler APIs,我认为您可以解决此问题。我不想估计这样做会有多少工作。
请注意,Eclipse允许您在其构建机制中包含您自己的注释处理。
答案 6 :(得分:0)
我不知道Java编译器中有这样的事情。但是您可以编写一个简单的程序,用文件中的linenumber替换__LINE__
之类的标记,并在编译之前配置构建过程以执行此工具。某种预处理器。