相同版本的代码优化是否有任何差异:OracleJava编译器ApacheJava编译器IBMJava编译器OpenJDKJava编译器。如果有什么代码可以展示不同的优化?或者他们使用相同的编译器?如果没有已知的优化差异,那么我在哪里可以找到关于如何测试不同优化的编译器的资源?
我花了大量时间使用的编译器只有javac
(正如其他人指出的,它在急切优化方面做得很少)和Eclipse编译器。
在编写Java反编译器时,我观察到Eclipse编译代码的方式有一些(通常令人沮丧)差异,但不是很多。其中一些可以被视为优化。其中:
>
Eclipse编译器似乎至少执行了一些重复的代码分析。如果两个(或更多?)代码块都会分支到单独但等效的代码块,等效的目标块可以通过多个条目跳转展平为单个块。我从未见过javac
执行这种类型的优化;始终会发出等效块。我记得的所有例子都发生在switch
语句中。这种优化减少了方法大小(因此也减少了类文件大小),这可能会提高加载和验证时间。它甚至可能会在解释模式下提高性能(特别是当所讨论的解释器html" target="_blank">执行内联时),但我认为这样的改进是微不足道的。我怀疑,一旦这个方法被JIT编译,它会有什么不同。这也使得反编译更加困难(grrr)。
基本块通常以与javac
完全不同的顺序发出。这可能只是编译器内部设计的副作用,也可能是编译器试图优化代码布局以减少跳转次数。这是我通常会留给JIT的那种优化,这种哲学似乎对javac
很有效。
不,它们不使用相同的编译器。我不能对这些优化和东西发表太多评论,但下面是一个例子,说明编译器在工作中是如何不同的。
public class Test {
public static void main(String[] args) {
int x = 1L; // <- this cannot compile
}
}
如果使用标准java编译器,它将抛出编译错误,并且不会创建类文件。
但是,如果您为java ECJ使用eclipse编译器,它不仅会抛出相同的编译错误,还会创建一个类文件(是的,一个不可编译代码的类文件,这使得ECJ,我不会说错,但有点棘手),看起来像这样。
public static void main(String[] paramArrayOfString)
{
throw new Error("Unresolved compilation problem: \n\tType mismatch: cannot convert from long to int.\n");
}
话虽如此,这只是两个编译器之间的问题。其他编译器可能有自己的工作方式。
附言:我从这里举了一个例子。
相同版本的Oracle Java compiler Apache Java compiler IBM Java compiler OpenJDK Java compiler在代码优化方面是否存在任何差异。
虽然编译器可能非常不同,但javac
几乎没有优化。主要的优化是常量内联,这在JLS中指定,因此是标准的(除了任何错误)
如果有什么代码可以演示不同的优化?
你可以做到这一点。
final String w = "world";
String a = "hello " + w;
String b = "hello world";
String c = w;
String d = "hello " + c;
System.out.prinlnt(a == b); // these are the same String
System.out.prinlnt(c == b); // these are NOT the same String
在第一种情况下,常量被内联,字符串在编译时连接。在第二种情况下,连接在运行时执行,并创建一个新的字符串。
或者他们使用的是同一个编译器?
没有,但是99%的优化都是在运行时由JIT执行的,所以对于给定版本的JVM,这些优化是相同的。
如果没有已知的优化差异,那么我在哪里可以找到关于如何测试编译器进行不同优化的资源?
如果有的话,我会很惊讶,因为这听起来不太有用。问题是JIT优化了字节代码的预构建模板,如果你试图优化字节代码,你可能会混淆JIT,代码变慢。也就是说,如果不考虑运行JVM,就没有办法评估优化。
问题内容: Eclipse的Java编译器是否只是包裹该程序的同一个内核的包装器,还是完全独立的编译器?如果是后者,为什么还要重新发明轮子呢? 问题答案: Eclipse实现了自己的编译器,称为Java Eclipse编译器(ECJ)。 它不同于Sun JDK附带的编译器javac。一个显着的区别是Eclipse编译器使您可以运行实际上未正确编译的代码。如果永远不会运行带有错误的代码块,则您的程序
我正在潜入angular 4,我试图理解编译。我已经读到,AOT和JIT都将TypeScript编译为JavaScript,无论是在服务器端还是在客户端。如果我在用Webpack和grunt构建它时编译它,并部署简化的javascript,那么AOT和JIT又是如何出现的呢?
主要内容:什么是编译器,什么是集成开发环境,选择哪种集成开发环境我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为 可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有 .exe 和 .com(其中 .exe 比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判断是否是可执行程序。 可执行程序的内部是一系列计算机指令和数据的集合,它们
所有编程语言都被翻译成机器代码,然后由硬件解释器执行。但是什么翻译译码器的代码,例如编译器代码和解释器代码?编译器翻译源代码,但编译器也用某种语言编写,那么什么翻译编译器代码/代码呢? 谢谢
问题内容: 即时编译器和解释器之间有什么区别,.NET和Java JIT编译器之间有什么区别? 问题答案: 即时编译是在执行之前将非本机代码(例如字节码)转换为本机代码。 从维基百科: JIT基于运行时环境中的两个较早的想法:字节码编译和动态编译。它在本地执行代码之前先在运行时将其转换,例如将字节码转换为本地机器代码。 一种解释执行程序。它可能有也可能没有抖动。 同样,来自维基百科: 解释器可能是
问题内容: 如果你给 它没有编译,但是带有花括号的相同代码是: 有什么解释? 问题答案: 基本上,变量声明只能在块中声明。 查看 Java语言规范中“语句”的语法 -它包括Block,但不包括LocalVariableDeclarationStatement- 后者是block语法的一部分。 这实际上是实用主义的问题:如果没有括号,则只能使用一个语句。如果没有后续语句,则声明变量是没有意义的,因为