Java最终布尔优化

Java最终布尔优化,java,optimization,Java,Optimization,请考虑以下设置: // debugger class public class Debug { // setting public final static boolean DEBUG = false; void print_checked( String s ) { if( DEBUG ) System.out.print( s ); } void print_unchecked( String s )

请考虑以下设置:

// debugger class
public class Debug
{
    // setting
    public final static boolean DEBUG = false;

    void print_checked( String s )
    {
        if( DEBUG )
            System.out.print( s );
    }

    void print_unchecked( String s )
    {
        System.out.print( s );
    }
}

// worker class
public class Algorithm
{
    Debug debugger;

    public void heavyWeightAlgorithmImplementation()
    {
        // method 1
        debugger.print_checked( "This method 1" );

        // method 2
        if( debugger.DEBUG )
            debugger.print_unchecked( "Or this method 2" );
    }
}
我读到Java中的
final boolean
s很可能会被优化掉。但是,正如在我的设置中一样,if条件位于另一个类中,并且当前在
print\u checked()
中实现。Java是否也优化了函数调用(方法1),还是必须像方法2那样重写所有内容


编辑#1:再次添加静态

Java会随着时间的推移而变化,它会变得更加复杂。所以把这个和一撮盐一起吃

在javac编译期间,如果编译器能够证明某段代码永远不会被访问,那么它将被删除

在运行时,现代Oracle JVM倾向于以解释模式运行字节码,在这种情况下,它将进行检查,直到JVM认为代码“热”到可以优化为止。此时,热点开始出现,它正朝着这样一种观点发展,即场将被假定为最终场,直到它证明不是最终场。此时,它将尝试预测分支,并相当积极地内联代码

但是,如果我回忆起,非静态字段的最终keword不能被运行时视为优化的最终keword,因为有方法在运行时更改这些字段的值。一种对JVM内部成员的憎恨


因此,出于您的选择,我推荐方法1,因为它减少了块需要复制的位置数量。但是,如果可能的话,我会将DEBUG字段设置为静态,这样可以更可靠地删除if语句。

在您的示例中,第一种方法更好。但是,如果在调试时需要一些串联操作,则第二个变量更可取

以下是一个例子:

if( debugger.DEBUG )
        debugger.print_unchecked( "Or this method 2" + oldValue + "//" + newValue);
在这种情况下,编译器可以避免不必要的字符串连接和调用toString()方法

这是我的测试:

public class DebuggerTest {

    static final int ITER_NUM = 5000000;
    public static class Debug
    {
        // setting
        public final static boolean DEBUG = false;
        private final List<String> collector = new ArrayList<String>(ITER_NUM);
        void print_checked( String s )
        {
            if( DEBUG )
                collector.add(s);
        }

        void print_unchecked( String s )
        {
            collector.add(s);
        }
    }

    public static void main(String[] args) {
        Debug debug = new Debug();
        long time = System.currentTimeMillis();
        for (int i = 0; i < ITER_NUM; i++) {
            debug.print_checked("Debug message " + i);
        }
        System.out.println("First: " + (System.currentTimeMillis() - time));
        debug = new Debug();
        time = System.currentTimeMillis();
        for (int i = 0; i < ITER_NUM; i++) {
            if (Debug.DEBUG)
                debug.print_unchecked("Debug message " + i);
        }
        System.out.println("Second: " + (System.currentTimeMillis() - time));
    }
}

我用jdk1.7编译了上面的示例,并在JDGUI中打开了*.class文件。
示例:

class Debug
{
    // setting
    public static final boolean DEBUG = false;
    void print_checked( String s )
    {
        if( DEBUG )
            System.out.print( s );
    }
    void print_unchecked( String s )
    {
        System.out.print( s );
    }
}

public class Main 
{
    public static void main(String[] argc)
    {
        Debug debugger = new Debug();
        debugger.print_checked(" This method 1");
        if (debugger.DEBUG)
            debugger.print_unchecked( "Or this method 2");
    }
}
京东图形用户界面:

// Debug.class
import java.io.PrintStream;
class Debug
{
  public static final boolean DEBUG = false;
  void print_checked(String paramString) {
  }
  void print_unchecked(String paramString) {
    System.out.print(paramString);
  }
}
// Main.class
public class Main
{
  public static void main(String[] paramArrayOfString)
  {
    Debug localDebug = new Debug();
    localDebug.print_checked(" This method 1");
  }
}

如您所见,“print\u checked”方法保留在Main.class代码中,但“print\u unchecked”被删除。我不确定,但我认为空方法“print_checked”也可能被Oracle JVM忽略。

我非常确定该方法将被内联,因此使用方法2将一事无成。您是否尝试过这两种方法以查看是否有任何可测量的差异?如果此代码不是非常耗时的,只需使用更易于维护的版本即可。您可能会节省0.000000000001秒。如果重复数十亿次,1ns的差异将变得显著。它将被优化。Java可以看到if语句真正读取
if(false)
,并将删除整个代码块。我会在JLSOh中寻找位置,好吧,我的错。误解了C++的
const
和Java的
final
的区别。现在将添加
static
。设置静态最终布尔值的一个好技巧是推断提供给JVM的-ea标志的值。通过这种方式,您可以关闭调试并从执行代码中剥离,直到您想要打开它,然后在不重新编译的情况下打开它。请参阅以获取如何执行此操作的示例。感谢您提供jd gui提示
// Debug.class
import java.io.PrintStream;
class Debug
{
  public static final boolean DEBUG = false;
  void print_checked(String paramString) {
  }
  void print_unchecked(String paramString) {
    System.out.print(paramString);
  }
}
// Main.class
public class Main
{
  public static void main(String[] paramArrayOfString)
  {
    Debug localDebug = new Debug();
    localDebug.print_checked(" This method 1");
  }
}