JEP 247: Compile for Older Platform Versions
Компиляция для более старых версий платформы
| Ответственный | Jan Lahoda |
| Тип | Feature |
| Область | JDK |
| Статус | Closed / Delivered |
| Выпуск | 9 |
| Компонент | tools / javac |
| Обсуждение | compiler dash dev at openjdk dot java dot net |
| Трудоёмкость | M |
| Длительность | L |
| Рецензенты | Alex Buckley, Brian Goetz, Jonathan Gibbons |
| Одобрен | Brian Goetz |
| Создан | 2014/09/10 16:56 |
| Обновлён | 2023/05/18 23:47 |
| Задача | 8058150 |
Аннотация
Доработать javac, чтобы он мог компилировать программы на Java для запуска на выбранных более старых версиях платформы.
Мотивация
У javac есть два параметра командной строки, -source и -target. Первый задаёт версию языка Java, которую принимает компилятор, второй — версию создаваемых им class-файлов. Однако по умолчанию javac компилирует с API самой последней версии платформы. Поэтому скомпилированная программа может случайно использовать API, которые есть только в текущей версии платформы. Такие программы не могут работать на более старых версиях платформы, какие бы значения ни были переданы параметрам -source и -target. Это давняя проблема удобства использования: пользователи ожидают, что с этими параметрами получат class-файлы, которые могут работать на версии платформы, указанной в -target.
Описание
Вводится новый параметр командной строки --release. Он автоматически настраивает компилятор так, чтобы тот создавал class-файлы, которые будут связываться с реализацией указанной версии платформы. --release N примерно эквивалентен следующему:
- для N < 9:
-source N -target N -bootclasspath <documented-APIs-from-N>, - для N >= 9:
-source N -target N --system <documented-APIs-from-N>.
Для N < 9 документированные API — это публичные API, которые находились в bootclasspath javac по умолчанию для JDK N.
Для N >= 9 документированные API включают (i) API, экспортируемые теми модулями образа JDK, которые входят в документацию JDK N, и (ii) API, экспортируемый модулем jdk.unsupported (описан в JEP 260). Иными словами, документированные API — это в основном API, экспортируемые пересечением множества модулей образа JDK и множества модулей, документированных для JDK N. Остальные модули образа JDK не наблюдаемы. Если используется --limit-modules, этот параметр может только дополнительно ограничить наблюдаемые модули, но не сделать наблюдаемыми другие модули. Доступ к внутреннему устройству модулей образа JDK запрещён.
Параметр --release N несовместим с другими параметрами, которые влияют на набор платформенных или системных классов. К ним относятся:
- для N < 9: параметры
-bootclasspath,-Xbootclasspath,-Xbootclasspath/a:,-Xbootclasspath/p:,-endorseddirs,-Djava.endorsed.dirs,-extdirs,-Djava.ext.dirs, задающие платформенные классы. - для N >= 9: параметры
--systemи--upgrade-module-path, задающие системные модули (то есть модули образа JDK), а также параметры--add-exports,--add-readsи--patch-module, если они изменяют системные модули. (--add-exports,--add-readsи--patch-moduleможно использовать для несистемных модулей, то есть модулей, которые не входят в образ JDK.) - для любого N: параметры
-sourceи-target, поскольку им автоматически присваивается значение N.
Предполагается, что документированные API будут меняться только в основных выпусках. В унаследованном случае, когда JAX-WS был обновлён с 2.0 до 2.1 в промежуточном выпуске JDK 6, документированным API считается JAX-WS 2.1.
Ограничение реализации --release: при компиляции используется версия Unicode не указанной целевой платформы, а текущей.
Реализация
Для JDK N и --release M, где M < N, нужны данные о сигнатурах документированных API выпуска M платформы. Эти данные хранятся в файле $JDK_ROOT/lib/ct.sym. Он похож на одноимённый файл в JDK 8, но не совпадает с ним. Файл ct.sym — это ZIP-файл с урезанными class-файлами, соответствующими class-файлам целевых версий платформы.
Для JDK N и --release N источником class-файлов, с которыми выполняется компиляция, служит собственный образ JDK. Однако список наблюдаемых модулей ограничен документированными модулями и модулем jdk.unsupported.
Риски и допущения
Репозиторий исходного кода JDK должен содержать описание API платформы прошлых выпусков. Это описание может быть довольно объёмным, и итоговые сборки JDK станут больше. Мы постарались максимально сократить эти дополнительные затраты места.