Внесение простых изменений в производительность уже скомпилированного jar?

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

  •  05-07-2019
  •  | 
  •  

Вопрос

Как и у многих пользователей log4j, у нас часто есть ведение журнала на уровне отладки, оценка которого требует больших затрат.Поэтому мы защищаем эти случаи с помощью такого кода, как:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())

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

Кажется, что должно быть довольно просто написать программу, которая принимает скомпилированный jar и защищает все вызовы _logger.debug с проверкой isDebugEnabled.Скорее всего, мы были бы готовы принять дополнительные накладные расходы на проверку isDebugEnabled во всех случаях.

Кто-нибудь пробовал этот подход или выполнял аналогичную постобработку jar?

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

Решение

Вы смотрели на AspectJ ? Это поддерживает аспекты, использующие переплетение байт-кода, и позволяет перехватывать в ранее скомпилированный файл .jar .

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

Вместо того, чтобы рассматривать изменение фляги, я бы искал решение, используя Инструментарий для байт-кода . Проблема будет заключаться в том, чтобы определить те части кода, которые вы хотите обернуть внутри .isDebugEnabled () - вам нужно будет идентифицировать объекты, которые используются только для вызовов log4j.

Я считаю, что хорошим решением было бы следующее код был бы эффективен как есть.

Учтите, что log4j устарел.Сам автор оставил его как есть, чтобы избежать нарушения совместимости, но он создал новый, SLF4J (http://www.slf4j.org/ ).Он предоставляет как фасад, так и реализацию, в соответствии с различием commons-logging / log4j, но без недостатков каждого из них...

Я полагаю, что в этом новом средстве ведения журнала вы можете отправлять параметры объекта в журнал и что уровень оценивается перед преобразованием объектов (в строку или иным образом).Идея состоит в том, чтобы использовать строку формата и параметры.


Наш код не использует slf4j, но у нас есть служебные методы, которые делают именно это.Он закодирован примерно следующим образом (по памяти)::

    public enum LogLevel {
       FATAL, ERROR, WARNING, INFO, DEBUG;

       public void log(Logger logger, String format, Object... parameters) {
         if (isEnabled(logger)) {
            logImpl(logger, String.format(format, parameters));
         }
       }
       public boolean isEnabled(Logger logger) {
         switch(this) {
           case WARNING : return logger.isWarningEnabled();
           case INFO : return logger.isInfoEnabled();
           case DEBUG : return logger.isDebugEnabled();
           default: return true;
         }
       }
       private void logImpl(Logger logger, String message) {
         switch(this) {
           case WARNING : logger.warn(message);
           // other cases
         }
       }
    }

Он используется как:

     public void myMethod(Object param) {
       LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
     }

Обновить :Если вам нужно вызвать метод из журнала...

  • Одна из возможностей заключается в использовании toString способ.Это вполне уместно если ваше ведение журнала носит "технический" характер, и будет использоваться также при отладке.

  • Если ваше ведение журнала более функционально (не предназначенный для разработчика), я предлагаю определить интерфейс (в этом случае он функционально надежен, поэтому полезно указать значение) :

    public interface Detailable { // the name could also suggest logging?
      String getFullDetails();
    }
    

    Реализуйте этот интерфейс в любом объекте, который необходимо передать как объект ведения журнала, со сложным вычислением для построения журнала.

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