__LINE__相当于Java?

时间:2009-08-28 11:19:40

标签: java logging portability

我正在寻找一种方法,在输出的消息中包含__LINE__作为编译时常量。

似乎存在各种解决方案,但__LINE__ in JS__LINE__ in C#中建议的运行时损失很大。它们通常始终基于运行时对象StackFrame作为log4j。

使用log4j在所需的基础上启用/禁用的可能性也不是一个选项,因为通常在发生错误时,启用行号为时已晚,并且内联代码似乎没有任何行号更多。 。是否有可能:

  1. 在编译之前预处理java源文件,理想情况下使用与Eclipse 1 集成的东西,因此也可以在开发平台上测试它。
  2. 能够在加载时预处理课程。然后,通过摊销,开销可以忽略不计。
  3. <子> 1。实际上我确实使用了一个丑陋的黑客:通过ANT技巧在构建服务器上结账后调用自定义预处理器

7 个答案:

答案 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();

当您需要时(例如catchif (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__之类的标记,并在编译之前配置构建过程以执行此工具。某种预处理器。