JRE版本必须等于或高于JDK版本?

4
我了解到JDK生成的字节码是通用的,也就是说它们只处理像内存映射、调用等操作...如果这是真的,那么是否意味着我可以编写一个具有JDK 1.7特性的程序,而不必担心它是否能在安装JRE 1.6的用户计算机上运行?(这只是一个例子,可能会出现更夸张的情况。)
因此,我的问题是:我能否编写一个包含1.7新功能的程序并在1.6中运行?

2
不,字节码或类有版本限制。这意味着Java 6无法读取/执行Java 7编译的类。这可以防止在Java 6及以下版本中某些Java 7功能不可用的问题。您可以使用Java 7生成适用于Java 6的“兼容”类,但这将消除在代码中使用Java 7功能的可能性。 - MadProgrammer
你对哪些具体的“新事物”感兴趣? - Andrew Thompson
“我读过JDK生成的字节码是通用的。” 我认为你不理解这意味着什么,或者从你读到那里的任何东西都不要再去读了。 - Brian Roach
我只是在说,如果你真的想做的话,你可以做到。不过除了个人使用外,这可能不是一个好主意。 - Antimony
了解关于java.lang.UnsupportedClassVersionError的内容。 - Amit G
显示剩余3条评论
2个回答

7
可以翻译为:

我能用1.7的新功能编写程序并在1.6中运行吗?

不行。Java不支持向后兼容。

请注意,可以通过使用交叉编译选项在1.7 JDK中创建与Java 1.6 JRE兼容的代码,但是该代码只能使用版本1.6中可用的类、属性、方法和语言特性。


1
“我能用1.7的新特性写程序并在1.6上运行吗?” 简短的回答是可以,但它不被官方支持。你需要采用一些技巧,但如果你真的想要这样做,你可以让它工作。虽然我不建议在重要项目中这样做。 总体来说,字节码不向后兼容,因为每个类文件都包含一个版本字段。JVM将拒绝运行高于其构建版本的类(低版本当然没问题)。默认情况下,Java 7附带的javac将创建版本为51.0的类,这意味着它们只能由Java 7或更高版本的JVM执行。 然而,这并不意味着如果你真的想要创建Java 6兼容代码就不可能。你可以告诉编译器生成早期版本的类文件。这只意味着你将无法使用新版本引入的库和字节码级别功能。
幸运的是,版本51.0实际上没有引入javac使用的任何新的字节码特性。Java 7中的所有新功能都是在编译时实现的 - 字节码除了版本外并没有任何不同!这意味着只要它不依赖于标准库更新(例如Try With Resources需要库支持),任何Java 7类都可以工作。
不幸的是,javac拒绝将Java 7编译为版本50.0。但是你可以手动或使用工具更改字节码版本字段。由于没有新的字节码特性,它将正常工作。
附:内存映射由VM完成。没有字节码指令。但你有正确的想法。

1
幸运的是,版本51.0实际上没有引入Java使用的任何新字节码特性。这完全是错误的。实际上,整个答案都是错误的。 - Brian Roach
1
不要管它。该陈述仍然是错误的。除此之外,与其告诉别人没有区别,显然是出于“未知原因”而这可能会导致他们可能会入侵二进制文件,也许使用已被Oracle淘汰的8年旧版本的JVM来运行,为何不坚持实用和现实世界的答案,也就是,不行。 - Brian Roach
更准确地说,可以认为 javac 没有使用 INVOKEDYNAMIC 而不是“Java”。我还想补充一点,一些字节码框架有意降低类的版本,以使这些类可以通过验证器,因为验证器不会检查版本50的堆栈映射。这些都是使用案例。 - Rafael Winterhalter
@Raphw 确实。我会更改以澄清这一点。理论上,另一个Java编译器可以生成invokedynamics。 - Antimony
这并不奇怪,因为它旨在为JVM上的非Java语言而设计(尽管一旦Java 8发布后,它可能也会用于lambda)。 - Antimony
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接