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

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

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

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

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

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

Ответы

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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