Как удалить отладочные инструкции из производственного кода в Java

Возможно ли, чтобы компилятор удалял операторы, используемые для целей отладки (например, ведение журнала) из производственного кода? Операторы отладки должны быть отмечены каким-то образом, возможно, с помощью аннотаций.

Легко установить свойство (debug = true) и проверить его в каждом операторе отладки, но это может снизить производительность. Было бы неплохо, если бы компилятор просто запустил инструкции отладки.

Ответы

Ответ 1

Две рекомендации.

Во-первых: для реального ведения журналов используйте современный пакет регистрации, например log4j или java, встроенный в журнал. Не беспокойтесь о производительности настолько, что проверка уровня регистрации на порядок составляет наносекунды. (это целочисленное сравнение).

И если у вас более одного оператора журнала, защитите весь блок:

(log4j, например:)

if (logger.isDebugEnabled()) {

  // perform expensive operations
  // build string to log

  logger.debug("....");
}

Это дает вам дополнительную ведение журнала контроля во время выполнения. Необходимость перезапуска и запуска отладочной сборки может быть очень неудобной.

Второе:

Вы можете найти утверждения больше того, что вам нужно. Утверждение - это оператор, который вычисляет логический результат с необязательным сообщением:

 assert (sky.state != FALLING) : "The sky is falling!";

Всякий раз, когда это утверждение приводит к ложному, утверждение терпит неудачу и вызывается AssertionError, содержащее ваше сообщение (это неконтролируемое исключение, предназначенное для выхода из приложения).

Оптимальная вещь: они обрабатываются специальными JVM и могут переключаться во время выполнения вплоть до уровня класса с использованием параметра VM (без необходимости перекомпиляции). Если он не включен, накладные расходы равны нулю.

Ответ 2

public abstract class Config
{
    public static final boolean ENABLELOGGING = true;
}

import static Config.*;

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        if (ENABLELOGGING)
        {
            log("Hello, logging world.");
        }
    }
}

Компилятор удалит блок кода с помощью "Hello, logging world". в нем, если для ENABLE_LOGGING установлено значение true, поскольку это статическое конечное значение. Если вы используете обфускатор, такой как proguard, тогда класс Config также исчезнет.

Обфускатор также допускает такие вещи:

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        Log.log("Hello, logging world.");
    }
}

import static Config.*;

public abstract class Log
{
    public static void log(String s)
    {
        if (ENABLELOGGING)
        {
            log(s);
        }
    }
}

Журнал журнала Log log log ничего не скроет в компиляторе и будет удален obfuscator вместе с любыми вызовами этого метода и, в конечном итоге, даже сам класс журнала будет удален.

Ответ 3

Другая возможность заключается в том, чтобы поместить оператор if в вашу функцию ведения журнала, вы получите меньше кода таким образом, но за счет некоторых дополнительных вызовов функций.

Я тоже не большой поклонник полного удаления кода отладки. Как только вы на производстве, вам, вероятно, понадобится доступ к отладочным сообщениям, если что-то пойдет не так. Если вы удалите всю отладку на уровне кода, это не является возможностью.

Ответ 4

Использовать Препроцессор Java? (google foo low, но это ссылка на старые форумы Joel, обсуждающие его)

Ответ 5

Java содержит своего рода препроцессор. Он называется APT. Он обрабатывает и генерирует код. На данный момент я не знаю, как это должно работать (я не пробовал). Но, похоже, это используется для такого рода вещей.

Ответ 6

Я также очень рекомендую использовать фреймворк протоколирования.

logger.IsDebugEnabled() не является обязательным, это просто, что может быть быстрее проверить, находится ли система на уровне отладки перед протоколированием.

Использование среды ведения журнала означает, что вы можете настраивать уровни ведения журнала "на лету" без перезапуска приложения.

У вас может быть запись:

logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")

Ответ 7

Этот " трюк кажется, что ваши отладочные заявления исчезли

public static final boolean DEBUG = false;

if (DEBUG) { //disapeared on compilation }

post сказал, что javac достаточно умен, чтобы проверить static final boolean и исключить операторы отладки. (Я лично не пробовал)

Для ведения журнала я лично не хочу видеть код вроде:

if (logger.isDebugEnabled()) {
    logger.debug("....");
}
realImportantWork();

Ведение журнала меня отвлекает от realImportantWork(). Правильный способ для меня:

logger.debug("....");
realImportantWork()

плюс конфигурация, которая исключает все отладочные сообщения в разделе "Производство".

Я имею в виду, что элемент управления logger.isDebugEnabled() должен быть базой регистрации, а не моей работой. Большинство систем ведения журналов поддерживают такие понятия, как "logger", "LogLevel".., которые могут сделать трюк.

Ответ 8

Чтобы ответить на ваш вопрос, я не знаю.

Но вот еще одно решение вашей проблемы: На мой взгляд, есть два утверждения, которые сталкиваются друг с другом здесь: "отладочные заявления" и "производственный код".

Какова цель отладочных инструкций? Помогите избавиться от ошибок во время (единичного) тестирования. Если часть программного обеспечения правильно протестирована и работает в соответствии с требованиями, операторы отладки - это не что иное, как OBSOLETE.

Я категорически не согласен с оставлением каких-либо отладочных инструкций в производственном коде. Бьюсь об заклад, никому не мешает тестировать побочные эффекты кода отладки в производственном коде. Код, вероятно, делает то, что он должен делать, но делает ли он больше? Все ваши #defines работают правильно и действительно принимают ВСЕ код отладки? Кто анализирует 100000 строк предварительно обработанного кода, чтобы узнать, исчезли ли все файлы отладки?

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