Почему вызов LoggerFactory.getLogger (...) каждый раз не рекомендуется? - PullRequest
42 голосов
/ 13 октября 2010

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

public class MyClass {
    final static Logger logger = LoggerFactory.getLogger(MyClass.class);

    public void myMethod() {
        //do some stuff
        logger.debug("blah blah blah");
    }
}

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

public class MyLoggerWrapper {
    public static void debug(Class clazz, String msg){
        LoggerFactory.getLogger(clazz).debug(msg));
    }
}

и просто используя его так:

public class MyClass {

    public void myMethod() {
        //do some stuff
        MyLoggerWrapper.debug(this.getClass(), "blah blah blah");
    }
}

Я предполагаю, что создание экземпляра логгера каждый раз, когда мы ведем логарифмизацию, довольно дорого, но я не смог найти ни одного документа, подтверждающего это предположение. Кроме того, он говорит, что, безусловно, фреймворк (LogBack или Log4J, который мы все еще решаем) будет «кэшировать» регистраторы, а также то, что в любом случае серверы работают намного ниже своей емкости, поэтому это не проблема.

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

Ответы [ 12 ]

1 голос
/ 13 ноября 2017

Есть две причины, почему подход вашего босса не достигает того, что он думает.

Меньшая причина в том, что затраты на добавление статического регистратора незначительны. В конце концов, настройка логгера является частью этой довольно длинной последовательности:

  • Найдите класс, то есть пройдитесь по всем файлам .jar и каталогам. Java-код Довольно большие накладные расходы из-за вызовов файловой системы. Может создавать вспомогательные объекты, например с File.
  • Загрузите байт-код, т.е. скопируйте его в структуру данных внутри JVM. Родной код.
  • Проверить байт-код. Родной код.
  • Свяжите байт-код, то есть переберите все имена классов в байт-коде и замените их указателями на упомянутый класс. Родной код.
  • Запуск статических инициализаторов. Вызванные из нативного кода, инициализаторы - это, конечно, Java-код. Регистратор создается здесь.
  • Через некоторое время, возможно, JIT-скомпилирует класс. Родной код. Огромные накладные расходы (в любом случае по сравнению с другими операциями).

Кроме того, ваш босс ничего не экономит.
Первый вызов LoggerFactor.getLogger создаст регистратор и поместит его в глобальную хэш-карту name-to-Logger. Это произойдет даже для вызовов isXxxEnabled, потому что для этого вам нужно сначала создать объект Logger ...
Объект Class будет нести дополнительный указатель для статической переменной. Это компенсируется накладными расходами при передаче параметра clazz - дополнительной инструкции и дополнительной ссылки размером с указатель в байт-коде, поэтому вы теряете хотя бы один байт в размере класса.

Код также проходит через дополнительную косвенную ссылку, LoggerFactory.getLogger(Class) использует Class#getName и делегирует LoggerFactory.getLogger(String).

Теперь, если ваш босс не после исполнения, а после возможности просто скопировать статическое объявление, он может использовать функцию, которая проверяет стек вызовов и извлекает имя класса. Функция должна быть аннотирована @CallerSensitive, и это все еще необходимо проверять при каждом использовании новой JVM - нехорошо, если вы не контролируете JVM, на которой пользователь запускает код.

Наименее проблематичным подходом было бы иметь IDE, которая проверяет создание экземпляра регистратора. Это, вероятно, означает поиск или написание плагина.

0 голосов
/ 14 декабря 2015

Возможно, я пропустил это в одном из предыдущих комментариев, но я не увидел упоминания о том, что логгер статический , вызов LoggerFactory выполняется ОДИН РАЗ (для каждого экземпляра класса) -поэтому первоначальное беспокойство о множественных вызовах для создания регистратора просто неверно.

Другие комментарии, касающиеся всех проблем с добавлением классов упаковки, также очень важны.

...