用于循环优化的Java

时间:2015-12-01 19:41:59

标签: java optimization

Java Runtime会对以下代码片段执行哪些优化?字节码没有显示任何优化但是我觉得Java应该采用for循环的最后一个值而不运行整个for循环,因为String是一个基本的Java类。

请注意。这个问题是在课堂考试中提出来的;但是,我无法提供足够的证据来支持我的主张。

public class Main {

    public static void main(String[] args) {
        String str = null;
        for (long i = 0; i < 10000000000L; i++) {
            str = new String("T");
        }

        System.out.println(str);
    }
}

1 个答案:

答案 0 :(得分:1)

虽然我无法确切地说明jit编译器正在做什么,但是你要求它做的优化(确定完全跳过循环体是安全的)实际上是非常困难的,并且所以我非常怀疑它已经完成了。无论String是一个&#34;基本的Java类&#34;。

,都是如此

为了更好地理解,首先让我们假设我们正在创建一个任意类Foo的实例,而不是String。如果我们知道两件事情,那么跳过所有那些Foo对象的创建是安全的:调用new Foo()没有任何可观察到的副作用;并没有提到Foo&#34;逃脱&#34;循环体。

可观察到的副作用就像设置静态成员的值(例如,如果Foo类保持静态计数的所有时间Foo()已被调用)。参考转义的一个示例是this内的Foo()变量是否传递到其他地方。

请注意,仅仅查看Foo()是不够的,您需要查看Foo的超类&#39;构造函数(以及链到Object的所有方式)。然后,您需要查看在初始化每个对象时执行的所有代码。然后查看该代码调用的所有代码。这将是一项大量的分析,即时及时#34;

public class Foo extends Bazz{
    static int count = 0;

    public Foo(){
        // Implicit call to Bazz() has side effect
        count++; // side effect
        Bazz.onNewFoo(this); // reference escaping
    }

    Bazz bazz = new Bazz();  // side effect
    {
        Bazz.onNewBazz(this.bazz); // reference escaping
    }
}

class Bazz{
    static int count = 0;

    static List<Foo> fooList = new LinkedList<>();
    static List<Bazz> bazzList = new LinkedList<>();

    static void onNewFoo(Foo foo){
        fooList.add(foo);
    }

    static void onNewBazz(Bazz bazz){
        bazzList.add(bazz);
    }

    public Bazz(){
        count++;
    }
}

你可能认为我们应该让javac为我们做这个分析和优化。问题是,没有办法保证编译时类路径上的Foo()版本与运行时类路径上的版本相同。 (这是Java的一个非常有价值的功能 - 它允许我将我的应用程序从Glassfish移动到Tomcat而无需重新编译)。因此,我们不能信任在编译时完成的分析。

最后,要意识到String与Foo没有什么不同。我们仍然需要运行该分析,并且没有办法事先进行分析(我为什么可以升级我的JRE而不重新编译我的应用程序)