Компиляция Java 7 на Java 6
Я знаю, что функции времени исполнения Java 7 недоступны с Java 6, но поскольку новый байт-код не был добавлен, новый байт-код invokedynamic
применим только для не-Java Языки, мне было интересно, как сложно было бы преобразовать исходный код Java 7 (новый оператор switch
, оператор алмаза) в чистую Java 6 (т.е. чтобы можно было преобразовать исходный код в Java 7 без потери совместимости с Java 6).
Любые указатели?
Ответы
Ответ 1
Отметьте выходной файл .class с помощью Java 7 javac с версией 1.6.0 (т.е. 0x32)
printf "\x00\x00\x00\x32" |dd of=Example.class seek=4 bs=1 count=4 conv=notrunc
(согласно http://en.wikipedia.org/wiki/Java_class_file#General_layout)
Если вы поместите это (используя $1 для имени файла) в j6patch
, вы можете делать все файлы классов с помощью:
find . -name \*.class |xargs -I {} ./j6patch {}
Я использовал это на большой базе данных (~ 4.8 MB jar) и даже использовал RetroTranslator
на java 6 jar, поэтому возможности языка Java 7 можно использовать в приложении, которое работает на Java 5. Также компилятор Java 7 (javac
) делает множество дополнительных оптимизаций (например, анализ побега), что очень заметно повышает производительность.
Использование RetroTranslator
с -verify -target 1.5
и JRE 1.6 фреймами времени выполнения позволяет проверить, не используются ли функции времени исполнения Java 7.
Ответ 2
Насколько я знаю, на данный момент решения этой проблемы нет. Лучше всего было бы расширить retrotranslator для работы с конструкциями Java 1.7. Оператор бриллианта должен быть очень простым, так как он вообще не требует модификации байт-кода.
Ваше утверждение "новый байт-код добавлен" неверен: существует новый код с активированным байтом, и, что еще более важно, есть несколько случаев, когда сгенерированный байт-код недействителен для 1.6 JRE, поэтому ретротранслятор должен будет исправить что.
Ответ 3
Вы правы, что invokedynamic инструкция не используется Java, однако есть и другие связанные изменения, которые могут быть использованы в Java. Invokedynamic полагается на новый "Механизм динамического связывания - метод ручек", для которого есть некоторые изменения в invokevirtual инструкции. Более подробную информацию вы можете найти в в этой статье в разделе "Новый механизм динамического связывания: методы обработки".
Обработчики методов также обеспечивают более быструю альтернативу отражению и, следовательно, полезны в Java. Преобразование кода с использованием дескрипторов методов в Java 6 было бы невозможным, поскольку функция использует Java 7 VM.
Ответ 4
Возможно, некоторые из них работают, но попробуйте следующее:
Добавьте компилятор Java Eclipse Java в свой путь к классам. Он находится в плагине org.eclipse.jdt.core
(найдите org.eclipse.jdt.core_*.jar
в папке plugins
).
Этот JAR содержит компилятор и синтаксический анализатор. Вы можете вызвать парсер самостоятельно, а затем использовать ASTVisitor
для перемещения дерева синтаксического анализа.
Затем вы можете изменить дерево и создать новый исходный код из этого, который можно скомпилировать, как обычно.
Возможно, даже возможно "предварительно обработать" дерево AST, прежде чем компилятор будет генерировать байтовый код; это избавит вас от шага "записывать источники на диск и скомпилировать их оттуда".