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

StackOverflow https://stackoverflow.com/questions/32041

Вопрос

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

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

Это было полезно?

Решение

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

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

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

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

if (logger.isDebugEnabled()) {

  // perform expensive operations
  // build string to log

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

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

Второй:

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

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

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

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

Другие советы

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". в нем if 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 будет удален.

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

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

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

Java содержит какой-то собственный препроцессор.Это называется ПОДХОДЯЩИЙ.Он обрабатывает и генерирует код.На данный момент я не уверен, как это должно работать (я еще не пробовал).Но, похоже, он используется для подобных вещей.

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

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

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

Вы могли бы вести журнал следующим образом:

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

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

public static final boolean DEBUG = false;

if (DEBUG) { //disapeared on compilation }

Тот Самый Публикация сказал , что javac достаточно умен, чтобы проверить static final boolean и исключите инструкции debug.(Я лично этого не пробовал)

Что касается ведения журнала, то лично мне не нравится видеть код, подобный:

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

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

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

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

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

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

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

Какова цель отладочных инструкций?Помогите избавиться от ошибок во время (модульного) тестирования.Если часть программного обеспечения должным образом протестирована и работает в соответствии с требованиями, инструкции debug являются не чем иным, как УСТАРЕВШИМИ.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top