2009-08-28 4 views
15

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

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

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

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

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

+0

Просто для моего любопытства: зачем вам номер строки в журналах? Когда возникает ошибка, у вас есть полная stacktrace, которая указывает номер строки ... – romaintaz

+3

Иногда в исключении вместо номера строки у меня есть что-то вроде 'Util.java (Inlined Compiled Code)'. И иногда я не имею никакого исключения, просто регистрирую информацию: «быть здесь», «быть здесь», я не хотел беспокоиться о наличии уникальных сообщений (номер строки делает их уникальными в любом случае) –

+0

JVM должен уметь справиться с этой ситуацией. Какую версию Java вы используете? –

ответ

8

При компиляции с опцией 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+ номером текущей строки. Это позволяет исправить номер строки на месте.

+0

Почему 'new Exception(). GetStackTrace()', а не 'Thread.currentThread(). GetStackTrace()'? –

+0

Нет причин, кроме того, что я не стал искать класс Thread для того, как получить текущий стек, и я знал, что у него есть исключение :) –

+0

+1 для решения, которое может быть использовано и в моей среде разработки (просто найдите и замените «Thread ....» номером строки в процессе сборки) –

13

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

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

public static int lineNumber() { 
    return Thread.currentThread().getStackTrace()[2].getLineNumber(); 
} 
+2

Отладочная информация о строке должна быть скомпилирована в файл-класс, чтобы получить доступ к этой информации. – Mnementh

0

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

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

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

0

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

+0

Это именно то, что я хотел бы заменить (см. Сноску 1.) –

1

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

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

5

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

4

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

Смежные вопросы