Подтвердить что ты не робот

Будет ли код, содержащий лямбда-выражения, работать на более старой JVM, скажем, для java 1.6?

Lambdas были представлены в Java8. Будет ли код, содержащий лямбда-выражения, работать на более старой JVM, скажем, для java 1.6? Меня беспокоит бинарная совместимость, а не совместимость с исходным кодом. Это простой вопрос "Да/Нет".

Спасибо.

4b9b3361

Ответ 1

Oracle очень старательно поддерживает язык Java и байт-код JVM язык отдельно. Только спецификация языка Java говорит, что означает программа, содержащая выражение лямбда, она ничего не говорит о как эта программа должна быть скомпилирована или интерпретирована.

Это означает, что в спецификации языка Java ничего не существует, что запрещает компиляцию этих лямбда-выражений таким образом, что результирующий код может быть выполнен с помощью Java 6 JVM, но в спецификации языка Java нет ничего, что гарантировало бы это тоже. Каждому поставщику Java разрешено кодировать лямбда-выражения любым способом. (Очевидно, что по прагматичным причинам большинство из них пытаются сопоставить то, что делает Oracle довольно близко.Таким образом, например, отладчики/декомпилирующие/инструменты, которые могут понимать и перерабатывать lambdas, закодированные Oracle javac, будут автоматически работать с байт-кодом, произведенным компилятором IBM J9 JDK Java.)

Компилятор javac, который поставляется с Oracle JDK, кодирует лямбда-выражения с использованием довольно сложного механизма LambdaMetafactory, MethodHandle s и invokedynamic. Последний был только представлен в Java 7 JVM, поэтому это означает, что для конкретной кодировки, используемой Oracles JDK javac, требуется, по крайней мере, Java 7 JVM. Но другие кодировки, безусловно, возможны, ни один из этих сложных механизмов не является действительно необходимым, это просто оптимизация производительности. Вы можете, например, закодировать Lambda Expressions как внутренние классы, которые будут работать вплоть до Java 1.1 JVM - это ведь точно, как мы написали "бедный человек лямбда", до Java 8; это также то, как оригинальные предложения для lambdas и даже ранние предварительные просмотры Java 8 реализовали его, в конце концов, развитие lambdas в Java заранее датируется даже Java 7 и invokedynamic.

Существует компилятор RetroLambda, который компилирует байт-код Java 8 JVM (а не исходный код Java!), созданный Oracle JDK javac к Java 7 JVM bytecode, Java 6 JVM bytecode или Java 5 JVM bytecode. Используя этот компилятор, вы можете создать файл класса, содержащий байт-код, который будет запускаться на любом Java 5 или более новом JVM из исходного кода Java 8, который использует (почти) все функции Java 8.

Ответ 2

Короткий ответ: это зависит.

Если вы полностью ограничены Oracle javac и библиотеками, ответ: no; по следующим причинам.

Java-байт-код содержит основной номер версии. По умолчанию компилятор Java 8 помещает java8 в данные. Любая старшая JVM просто отказывается запускать этот код. Возможно, хотя можно сказать компилятору Java 8, чтобы создать байт-код, совместимый с более старыми JVM. Но: для того, чтобы старшая JVM выполняла такие "специальные" файлы классов, вам нужно all, чтобы ее зависимости были доступны!

И там он ломается: Lambdas использует инструкцию invokedynamic bytecode, которая не существует в Java 6. И помимо этого, компилятор использует большое количество материалов библиотеки Java при компиляции lambdas - все они добавляются после java 6.

Итак, даже если вам удастся скомпилировать lambda с использованием исходного кода на байт-код Java 6, эта инструкция недоступна, и вам также необходимо предоставить все эти другие классы.

Но: как объясняет другой отличный ответ, есть альтернативы javac, которые позволяют использовать лямбда на более старых JVM.

Но: будьте осторожны, как потратить свою энергию. Java 6 все еще мертв для "серверной java". Таким образом, использование этих альтернатив подходит для таких платформ, как Android, но когда вы все еще используете JVM Oracle Java 6, вам стоит потратить свою энергию на обновление этой системы до текущей версии Java.

Ответ 3

Как говорили другие: no

Файлы классов, созданные компилятором javac, версируются. Все, что выпускается Java 8, помечается как обязательное Java JVM по умолчанию. Старые версии JVM не будут принимать двоичный файл.

Если вы хотите скомпилировать более старую платформу, вы должны указать javac: javac -target 6. Как только вы добавите этот параметр в командную строку, ваш компилятор Java 8 потребует, чтобы вы указали -source 6 (или ниже). Поэтому он не будет принимать код, содержащий лямбда-выражения.