__LINE__ эквивалент в Java? - PullRequest
       16

__LINE__ эквивалент в Java?

17 голосов
/ 28 августа 2009

Я ищу способ включить __LINE__ в качестве постоянной времени компиляции в выводимых сообщениях.

По-видимому, существуют различные решения, но с большим штрафом за время выполнения, как предложено в __LINE__ в JS и __LINE__ в C # . Обычно они всегда основаны на объекте времени выполнения StackFrame как log4j.

Использование возможности log4j для включения / выключения на необходимой основе также не вариант, так как обычно, когда возникает ошибка, слишком поздно включать номера строк, и встроенный код, похоже, не имеет каких-либо номеров строк. Больше. , Было бы возможно либо:

  1. Предварительная обработка исходных файлов Java перед компиляцией, в идеале с чем-то, интегрированным с Eclipse 1 , чтобы его можно было также протестировать на платформе Developpement.
  2. Уметь предварительно обрабатывать класс во время загрузки. Накладные расходы будут незначительными при амортизации.

1. На самом деле я использую некрасивый хак: вызов собственного препроцессора сразу после извлечения на сервере сборки с помощью трюков ANT

Ответы [ 7 ]

13 голосов
/ 28 августа 2009

Невозможно получить эффект __LINE__ в C, который происходит во время компиляции.

Вы можете получить номер строки, вызвав такую ​​функцию во время выполнения,

public static int lineNumber() {
    return Thread.currentThread().getStackTrace()[2].getLineNumber();
}
9 голосов
/ 28 августа 2009

Если вы скомпилируете с опцией debug=line, информация о строке существует в файле класса, но виртуальная машина может выбросить ее во время выполнения. Это зависит от некоторых параметров, которые вы можете указать при запуске 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+ на текущий номер строки. Это позволяет зафиксировать номер строки на месте.

6 голосов
/ 18 июля 2012

Я обнаружил, что этот класс облегчает задачу, если вы ищете протоколирование типа "попал сюда, попал сюда". У меня есть файл 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" во втором случае.

5 голосов
/ 31 марта 2010

Это правда, что из коробки эти макросы недоступны. Однако, используя инструментарий и отладочную информацию, вы можете это реализовать. чек http://www.gallot.be/?p=85

1 голос
/ 28 августа 2009

Я бы использовал для этого каркас регистрации, и пусть он разберется с грязными деталями. И java.util.logging, и logback могут легко отображать информацию о вызывающем абоненте, аналогичную той, которую может предоставить LINE .

Основным преимуществом является то, что информация вычисляется только при необходимости, поэтому отсутствие вывода означает отсутствие накладных расходов.

0 голосов
/ 28 августа 2009

Я не знаю об этом в Java-компиляторе. Но вы можете написать простую программу, которая заменит маркер типа __LINE__ на номер белья в файле и сконфигурировать ваш процесс сборки для запуска этого инструмента перед компиляцией. Какой-то препроцессор.

0 голосов
/ 28 августа 2009

Из коробки Я не думаю, что Java предлагает то, что вам нужно.

Однако, если бы вы написали свой собственный процессор аннотаций и использовали API компилятора Java 6.0 Я думаю, вы могли бы решить эту проблему. Мне было бы все равно угадывать, сколько работы это займет.

Обратите внимание, что Eclipse позволяет вам включать собственную обработку аннотаций в свой механизм сборки.

...