如何用Java 11生成代码,但要针对Java 8及更高版本? [英] How to produce code in Java 11, but target Java 8 and above?

查看:344
本文介绍了如何用Java 11生成代码,但要针对Java 8及更高版本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个小型库,出于明显的原因,我想使用Java 11的所有功能(我现在猜想的模块除外)来生成代码,但是我希望该库与Java 8及更高版本兼容。

I am working on a small library and for obvious reasons I would like to produce code using all the Java 11 features (except modules I guess for now), but I would like the library to be compatible with Java 8 and above.

当我尝试以下操作时:

javac -source 11 -target 1.8 App.java

我收到以下消息:

warning: source release 11 requires target release 11

...当我查看字节码时,我看到该类的版本为 0x37 (Java 11):

...and when I look at the byte code I see that the version of the class is 0x37 (Java 11):

$ xxd App.class
00000000: cafe babe 0000 0037 ...

Java 8无法加载它:

And Java 8 cannot load it:

Exception in thread "main" java.lang.UnsupportedClassVersionError: App has been
    compiled by a more recent version of the Java Runtime (class file version 55.0),
    this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

如何操作le提供这样的兼容性吗?我对所有构建工具都开放。

How do people provide such compatibility? I am open to all build tools.

对我来说,将高级语言(Java)转换为低级语言(字节码)似乎很容易。在我看来,当高级语言更改时,低级语言应保持不变。这就是为什么我认为有可能的原因。

For me it seems easy just to transform high-level language (Java) into low-level (bytecode). It appears to me that when the high-level language changes, the low-level should stay the same. That is why I thought it was possible.

更新

我是不要以为这个答案重复了移至OpenJDK-11却可以在Java 8中编译,因为在那里OP询问如何继续使用 Java 8 功能生成代码,但以Java 11为目标(这是著名的向后兼容性)。我的问题是相反的:我想用Java 11生成代码,但要针对Java8。我在提出问题之前研究该主题时遇到了这个问题。我发现它不适用于我的情况。

Guys, I don't think that this answer duplicates Move to OpenJDK-11 but compile in Java 8, because there the OP asks how to keep producing the code with Java 8 features, but target Java 11 (which is just a famous backward compatibility). My question is the other way around: I want to produce the code in Java 11, but target Java 8. I came across that question when I was researching the topic before posing the question. I didn't find it applicable to my situation.

另一个问题可以Java 8代码被编译为可以在Java 7 JVM上运行的确与我的问题相似,但是在2013年被问到,字节码显然在Java 7和Java 8之间发生了变化。

The other question Can Java 8 code be compiled to run on Java 7 JVM does look similar to my question, but it was asked in 2013 and the bytecode obviously changed between Java 7 and Java 8.

自Java 8以来,我认为字节码变化不大,这就是为什么我问这个问题。

I didn't think the bytecode changed that much since Java 8 that is why I asked this question.

推荐答案

尽管从理论上讲,使用复杂的工具可以将为JDK 11编译的类转换为JDK 8,但这并非微不足道。二进制级别有重大变化。

While conversion of classes compiled for JDK 11 to JDK 8 would be theoretically possible with a sophisticated tool, it’s not trivial. There are significant changes on the binary level.

首先,JDK 11引入了嵌套类型,这样就无需在访问 private 时生成综合访问器方法内部/外部类的成员。当然,这种访问在旧版本中将失败。

First, JDK 11 introduced nest types, which eliminates the need to generate synthetic accessor methods when accessing private members of inner/outer classes. Of course, such access would fail in older versions.

它还引入了动态常量,尽管我不知道Java语言是否在任何地方都利用了该功能。

It also introduced dynamic constants, though I don’t know whether the Java language exploits that feature anywhere. This is mainly intended for future versions.

然后,由于JDK 9,使用 invokedynamic 引用 java Java 8中不存在的.lang.invoke.StringConcatFactory

Then, since JDK 9, string concatenation gets compiled using invokedynamic referring to java.lang.invoke.StringConcatFactory which is not present in Java 8.

一个可行的功能是 private 接口中的方法,作为语言功能在Java 9中引入,但已经在Java 8中以二进制级别进行了处理。

A feature that could work, is private methods in interfaces, introduced in Java 9 as a language feature, but already handled on the binary level in Java 8.

Java 8也将无法处理模块定义,但我想,它们将被忽略。

Java 8 would also be unable to process module definitions, but I suppose, they would be ignored.

这篇关于如何用Java 11生成代码,但要针对Java 8及更高版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆