Java 对已编译的jar进行简单的性能修改?

Java 对已编译的jar进行简单的性能修改?,java,performance,jar,Java,Performance,Jar,像许多log4j用户一样,我们经常有调试级别的日志记录,评估起来很昂贵。因此,我们使用以下代码来保护这些案例: if( _logger.isDebugEnabled ) _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails()) 然而,这比普通的_logger.debug调用更难看,有时程序员没有意识到评估可能会很昂贵 似乎编写一个程序相当简单,它接受一个已编译的jar,并使用isDebugEnabl

像许多log4j用户一样,我们经常有调试级别的日志记录,评估起来很昂贵。因此,我们使用以下代码来保护这些案例:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())
然而,这比普通的_logger.debug调用更难看,有时程序员没有意识到评估可能会很昂贵

似乎编写一个程序相当简单,它接受一个已编译的jar,并使用isDebugEnabled检查保护所有的_logger.debug调用。我们可能愿意接受在所有情况下检查isDebugEnabled的额外开销


有没有人尝试过这种方法,或者对jar做过类似的后处理?

我不想修改jar,而是想使用。问题是要识别那些您想要包装在
.isDebugEnabled()
中的代码部分-您必须识别只用于log4j调用的对象。

我相信一个好的解决方案是代码将像现在一样高效

假设log4j已被弃用。它的作者自己保持原样,以避免破坏兼容性,但他创建了一个新的,SLF4J()。根据commons logging/log4j的区别,他提供了一个门面和一个实现,但没有每个门面的缺陷

我相信,在这个新的日志记录工具中,您可以将对象参数发送到日志记录,并且在转换对象(转换为字符串或其他)之前对级别进行评估。其思想是使用格式字符串和参数


我们的代码不使用slf4j,但我们有实用方法可以做到这一点。 它的编码大致如下(从内存中):

它被用作:

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

更新:如果需要调用日志中的方法

  • 一种可能性是使用
    toString
    方法。如果您的日志记录是“技术性的”
    ,这是合适的,并且在调试时也将使用它

  • 如果您的日志功能更强大(不针对开发人员),我建议定义一个界面(在这种情况下,它在功能上是合理的,因此提供含义很有用):

    在需要作为日志对象传递的任何对象中实现该接口,并通过复杂的计算来构建日志


    • 你看过吗?这支持使用字节码编织的方面,并且可以拦截。

      我不确定log4j是否已经这样做了(在打印一个大的、长的内容之前,内部检查isDebugEnabled=true)。。。你检查过了吗?log4j会检查日志级别本身(当然)。人们使用
      isDebugEnabled()
      标志的原因是,他们希望避免由构造字符串引起的开销(
      “有趣的是,我的foojes被搞糟了:“+getFullDetails()
      ”)等等。log4j首先检查isDebugEnabled。如果未启用调试,我试图避免评估getFullDetails。将对象传递到日志调用中没有帮助。成本在于评估getFullDetails。@Ted,如果您更改getFullDetails以提供一个对象,该对象在其toString方法中进行评估,这将有效地延迟工作。这将有助于所有情况,除了“程序员没有意识到评估可能很昂贵”的情况。您可以这样做:
      log.debug(“有趣的是,我的foojes被搞糟了:{}”,new Object(){String toString(){return getFullDetails())
      -但这比原来的更漂亮吗?:)我支持伊斋的建议。我将其与我看到的其他可能性以及在两者之间选择的标准结合在一起。我想你可以从
      debug
      上的
      ivokevirtual
      回溯,找到获得日志的
      getfield
      指令呃。不过,在某些情况下,日志调用的开始和结束位置可能不明确。这是值得研究的。非常有用,这与我所寻找的最接近。我看不出这对测试示例有什么帮助。即使您在
      Logger.debug(String)上设置了切入点
      使用
      around
      建议防止调用它,仍将调用
      getFullDetails()
           public void myMethod(Object param) {
             LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
           }
      
      public interface Detailable { // the name could also suggest logging?
        String getFullDetails();
      }