Как создать код на Java 11, но ориентироваться на Java 8 и выше? - PullRequest
0 голосов
/ 30 января 2019

Я работаю над небольшой библиотекой, и по понятным причинам я хотел бы создать код, используя все функции Java 11 (за исключением модулей, которые я предполагаю на данный момент), но я бы хотел, чтобы библиотека была совместима с Java 8 и выше.

Когда я пытаюсь это сделать:

javac -source 11 -target 1.8 App.java

я получаю следующее сообщение:

warning: source release 11 requires target release 11

... и когда я смотрю на байт-код, я вижу, чтоверсия класса 0x37 (Java 11):

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

И Java 8 не может его загрузить:

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)

Как люди обеспечивают такую ​​совместимость?Я открыт для всех инструментов сборки.

Мне кажется, просто преобразовать язык высокого уровня (Java) в язык низкого уровня (байт-код).Мне кажется, что когда меняется язык высокого уровня, уровень низкого уровня должен оставаться прежним.Вот почему я подумал, что это возможно.

ОБНОВЛЕНИЕ

Ребята, я не думаю, что этот ответ дублирует Перейдите в OpenJDK-11, но скомпилируйте вJava 8 , потому что там ОП спрашивает, как продолжать создавать код с Java 8 функциями, но ориентироваться на Java 11 (что является просто известной обратной совместимостью).Мой вопрос наоборот: я хочу создать код на Java 11, но нацеливаться на Java 8. Я столкнулся с этим вопросом, когда изучал эту тему, прежде чем сформулировать вопрос.Я не нашел это применимым к моей ситуации.

Другой вопрос Можно ли скомпилировать код Java 8 для запуска на Java 7 JVM действительно похоже на мой вопрос, но он был задан в2013 и байт-код явно изменились между Java 7 и Java 8.

Я не думал, что байт-код изменился так сильно после Java 8, поэтому я задал этот вопрос.

Ответы [ 4 ]

0 голосов
/ 09 мая 2019

Хотя преобразование классов, скомпилированных для JDK 11, в JDK 8 теоретически возможно с помощью сложного инструмента, оно не тривиально.На двоичном уровне произошли значительные изменения.

Во-первых, в JDK 11 введены типы nest , что устраняет необходимость генерировать синтетические методы доступа при доступе к private членам внутренних / внешних классов.Конечно, такой доступ не будет работать в более старых версиях.

В него также введены динамические константы , хотя я не знаю, использует ли язык Java эту функцию где-либо.Это в основном предназначено для будущих версий.

Затем, начиная с JDK 9, конкатенация строк компилируется с использованием invokedynamic, ссылаясь на java.lang.invoke.StringConcatFactory, которого нет в Java 8.

Функцией, которая может работать, являются private методы в интерфейсах, представленные в Java 9 как языковая функция, но уже обработанные на двоичном уровне в Java 8.

Java 8 также не сможетопределения модулей процесса, но я полагаю, они будут игнорироваться.

0 голосов
/ 30 января 2019

Я могу ошибаться, но, по крайней мере, знаю, javac не предназначен для использования таким образом.

Немного догадываюсь: вы можете попытаться проверить, работает ли --release 8 --target 8 (без указания параметра --source 11).

Но я сомневаюсь, что это сработает.Я думаю, что в javac нет поддержки для принятия N функций исходного кода, и они скомпилированы обратно к более ранним целевым версиям.

Конечно, компилятор может знать о необходимых преобразованиях, чтобы превратить исходный код N в (Nm) байт-код.Но это сделало бы компилятор намного более сложным, и каждый выпуск добавил бы к этому.Это также добавило бы драматические затраты на тестирование усилий.Я сомневаюсь, что сопровождающие компилятора готовы купить это.Это действительно не так, как это широко распространенный вариант использования.

Итак, «1013 * only » «решение», которое я знаю: ветвление и двойное обслуживание.И чтобы все было разумно, я бы просто оставил версию для Java 8, а может быть для Java 11.

0 голосов
/ 09 мая 2019

Нет, вы не можете скомпилировать исходный код Java 11 в двоичные файлы Java 8.

В терминах javac параметр -source не может быть больше, чем параметр -target.

Итак, если вы хотите создать двоичные файлы Java 8, ваши источники должны бытьнаписано в Java 8 (или ранее).Если вы не используете какие-либо функции языка Java 11, ваши источники в основном уже находятся в Java 8, так что это не должно быть слишком большой проблемой.

Обратите внимание, что вы все равно можете использовать JDK 11 для компиляции Java8 исходников в Java 8 двоичных файлов.Версия JDK может быть больше, чем исходная и / или целевая версии.

Примечание: документация javac ничего не говорит о том, что параметр -source должен быть меньше или равен -target параметр.Однако есть много неофициальных документов.Например, https://stackoverflow.com/a/9261298/691074

Насколько я могу судить, нет ни одного контр-примера того, как заставить такую ​​ситуацию работать.

0 голосов
/ 30 января 2019

Хотя я не видел ничего явного в javadoc для javac, я думаю, что вы можете указывать одну и ту же версию только для опций -source и -target.Функции Java 11 не поддерживаются в Java 8, хотя верно и обратное, более высокая версия Java может запускать код, скомпилированный в более низкой версии.Так что я не думаю, что можно скомпилировать код, написанный на Java 11, для запуска в Java 8.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...