mst*_*rap 93 java compiler-construction javac
使用相同的JDK(即相同的javac
可执行文件)时,生成的类文件是否始终相同?可能会有所不同,具体取决于操作系统或硬件?除JDK版本外,是否还有其他因素导致差异?是否有任何编译器选项可以避免差异?仅在理论上可能存在差异,或者Oracle是否javac
实际为相同的输入和编译器选项生成不同的类文件?
更新1我对生成感兴趣,即编译器输出,而不是类文件是否可以在各种平台上运行.
更新2通过'相同的JDK',我也意味着相同的javac
可执行文件.
更新3 Oracle编译器中理论差异与实际差异的区别.
[编辑,添加释义问题]
"在不同的平台上运行相同的javac可执行文件会产生不同的字节码的情况是什么?"
Joa*_*uer 68
我们这样说吧:
在.class
给定相同的.java
文件的情况下,我可以轻松地生成一个完全符合规范的Java编译器,它永远不会生成两次相同
我可以通过调整各种字节码构造或简单地向我的方法添加多余的属性(这是允许的)来做到这一点.
鉴于规范不要求编译器生成逐字节的相同类文件,我会避免依赖于 这样的结果.
但是,我已经检查了几次,使用相同的开关(和相同的库!)使用相同的编译器编译相同的源文件确实产生了相同的.class
文件.
更新:我最近偶然发现了这篇switch
关于String
在Java 7中实现on的有趣博客文章.在这篇博文中,有一些相关部分,我在这里引用(强调我的):
为了使编译器的输出可预测和可重复,这些数据结构中使用的映射和集合是
LinkedHashMap
s和LinkedHashSet
s而不仅仅是HashMaps
和HashSets
.在给定编译期间生成的代码的功能正确性方面,使用HashMap
并且HashSet
会很好 ; 迭代顺序无关紧要.但是,我们发现javac
根据系统类的实现细节,输出不会有所不同.
这很清楚地说明了问题:编译器不需要以确定的方式操作,只要它与规范匹配即可.然而,编译器开发人员意识到尝试通常是一个好主意(假设它不太昂贵,可能).
gab*_*sch 38
编译器没有义务在每个平台上生成相同的字节码.您应该咨询不同供应商的javac
实用程序以获得具体答案.
我将通过文件排序显示一个实际的例子.
假设我们有2个jar文件:my1.jar
和My2.jar
.它们被放在lib
目录中,并排放置.编译器按字母顺序读取它们(因为这是lib
),但顺序是my1.jar
,My2.jar
当文件系统不区分大小写时My2.jar
,my1.jar
如果它区分大小写.
的 my1.jar
具有类A.class
以的方法
public class A {
public static void a(String s) {}
}
Run Code Online (Sandbox Code Playgroud)
的My2.jar
具有相同的A.class
,但具有不同的方法签名(接受Object
):
public class A {
public static void a(Object o) {}
}
Run Code Online (Sandbox Code Playgroud)
很明显,如果你有电话
String s = "x";
A.a(s);
Run Code Online (Sandbox Code Playgroud)
它将在不同情况下编译具有不同签名的方法调用.因此,根据您的文件系统区分大小写,您将获得不同的类.
简答 - 没有
bytecode
对于不同的平台,它们不一定相同.它是JRE(Java运行时环境),它知道如何执行字节码.
如果您仔细阅读Java VM规范,您将会发现,对于不同的平台,字节码是相同的,这不一定是真的.
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
Run Code Online (Sandbox Code Playgroud)
检查次要版本和主要版本
minor_version,major_version
minor_version和major_version项的值是此类文件的次要版本号和主要版本号.总的来说,主要版本号和次要版本号决定了类文件格式的版本.如果类文件具有主版本号M和次版本号m,则我们将其类文件格式的版本表示为Mm.因此,类文件格式版本可以按字典顺序排序,例如,1.5 <2.0 <2.1.当且仅当v位于某个连续范围Mi.0 v Mj.m中时,Java虚拟机实现可以支持版本v的类文件格式.只有Sun可以指定符合Java平台特定发行版级别的Java虚拟机实现可支持的版本范围
通过脚注阅读更多内容
1 Sun的JDK 1.0.2版的Java虚拟机实现支持45.0到45.3的类文件格式版本.Sun的JDK 1.1.X版可以支持45.0到45.65535范围内的类文件格式.Java 2平台1.2版的实现可以支持45.0到46.0范围内的版本的类文件格式.
因此,调查所有这些表明在不同平台上生成的类文件不必相同.
归档时间: |
|
查看次数: |
7599 次 |
最近记录: |