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);
}
}
答案 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而不重新编译我的应用程序)