Нужно ли компилировать Java в байт-код?

Предписывает ли Спецификация языка Java, что Java компилируется в байт-код Java?

Насколько я понимаю, это не так:

JLS 1

Время компиляции обычно состоит из перевода программ в машинно-независимый байт-код [представление.

[...]

Язык программирования Java обычно компилируется в набор инструкций байт-кода и двоичный формат, определенный в Спецификации виртуальной машины Java, Java SE 9 Edition.

(выделено мной)

Я не могу найти других упоминаний о «байт-коде» или «байт-коде» в спецификации.

Означает ли это, что все манипуляции с байт-кодом технически не охватываются «языком Java», как это определено JLS, и технически полагаются на детали реализации?


person phant0m    schedule 29.11.2017    source источник
comment
Необходимо проверить, но это, вероятно, указано в спецификации JVM, а не в спецификации языка. Кроме того, начиная с Java 9, JShell (кажется, это название) позволяет выполнять код Java в оболочке без компиляции.   -  person AxelH    schedule 29.11.2017
comment
@AxelH это манипулирование байт-кодом? Я не думаю, что в спецификации JVM можно указать, что Java должна быть скомпилирована в байт-код Java.   -  person phant0m    schedule 29.11.2017
comment
Действительно, язык Java можно компилировать любым способом. Хотя спецификация JVM распространяется на байт-код. Виртуальная машина Java ничего не знает о языке программирования Java, только об определенном двоичном формате, формате файла класса. Файл класса содержит инструкции виртуальной машины Java (или байт-коды) и таблицу символов, а также другую вспомогательную информацию.   -  person bcsb1001    schedule 29.11.2017
comment
@AxelH Я не проверял JShell, но не будет ли это просто артефактом дистрибутива JDK? Кроме того, тот факт, что нет явного шага компиляции в байт-код, не означает, что Jshell не может этого сделать.   -  person phant0m    schedule 29.11.2017
comment
@ phant0m Я считаю более логичным найти спецификацию байт-кода в инструменте, который его использует. Не могли бы вы пояснить, это манипулирование байт-кодом? Я этого не понимаю. (JShell просто есть, к вашему сведению, это, скорее всего, скомпилировано, но по-своему)   -  person AxelH    schedule 29.11.2017
comment
@AxelH, что касается этого в кавычках, вы сказали, что его нужно проверить, но это, вероятно, соответствует спецификации JVM. Мне было интересно, имели ли вы в виду первую (должна ли Java быть...) или вторую часть (являются библиотеками для манипулирования байт-кодом вне языка Java) моего вопроса.   -  person phant0m    schedule 29.11.2017
comment
Я имел в виду Предписывает ли Спецификация языка Java, что Java компилируется в байт-код Java?   -  person AxelH    schedule 29.11.2017


Ответы (2)


Вы правильно заметили, что термин «обычно», а также отсутствие какого-либо описания байт-кода в JLS предназначены для того, чтобы определить язык программирования Java как можно более независимым от среды выполнения. Тем не менее, это не так просто:

Связь с предопределенными классами и интерфейсами

Как отмечалось выше, эта спецификация часто относится к классам API платформы Java SE. В частности, некоторые классы имеют особые отношения с языком программирования Java. Примеры включают такие классы, как Object, Class, ClassLoader, String, Thread, а также классы и интерфейсы в пакете java.lang.reflect, среди прочих. Эта спецификация ограничивает поведение таких классов и интерфейсов, но не дает для них полную спецификацию. Читатель отсылается к документации по API платформы Java SE.

Следовательно, эта спецификация не описывает отражение в деталях. Многие лингвистические конструкции имеют аналоги в Core Reflection API (java.lang.reflect) и Language Model API (javax.lang.model), но обычно они здесь не обсуждаются. Например, когда мы перечисляем способы создания объекта, мы обычно не включаем способы, которыми Core Reflection API может это сделать. Читатели должны знать об этих дополнительных механизмах, даже если они не упоминаются в тексте.

Таким образом, язык программирования Java — это больше, чем JLS, это также API платформы Java SE. И там у нас есть defineClass методов упомянутого ClassLoader класса, принимающих входные данные в формате файла класса. Таким образом, даже если мы используем другие средства развертывания, кроме файлов классов в формате байт-кода, полностью совместимая среда должна поддерживать этот формат в данном месте. Обратите внимание, что в Java 9 появились еще один метод, принимающий ввод в формате файла класса, который даже не требует отражения или реализации пользовательских загрузчиков классов.

Это исключает JavaME, в котором нет этих артефактов API, упомянутых в JLS, в противном случае у нас уже был пример среды Java, не поддерживающей манипулирование байт-кодом.

Но это все еще не дает полного ответа на вопрос, является ли манипулирование байт-кодом неязыковым, говоря о JavaSE или EE. Даже если поддержка формата байт-кода обеспечивается стандартным API, манипулирование байт-кодом зависит от деталей реализации, будь то инструментальный API, чья поддержка не является обязательной, или обработка скомпилированных файлов классов в их развернутой форме, в виде файловой иерархии, файлов jar или модуля. файлы, ни один из которых не гарантируется развернутой формой приложения (как было сказано в начале). Таким образом, действительно невозможно реализовать инструмент для работы с байт-кодом, который гарантированно работает с каждой возможной средой Java, хотя вам придется приложить немало усилий, чтобы создать среду, которая полностью совместим, но не работает с этими инструментами

person Holger    schedule 29.11.2017
comment
В настоящее время я просматриваю JLS и в настоящее время замалчиваю главы 12 и 13 JLS. В нем также говорится о загрузчиках классов и о выполнении программы Java в целом с точки зрения JVM, хотя прямо не говорится, что это приходится запускать на одном. Кажется, это еще раз подчеркивает вашу точку зрения, что это непросто - person phant0m; 29.11.2017

JSL не должен знать, как он будет прочитан JVM, он описывает только язык Java. Компилятор (JAVAC), предоставленный в JDK, делает ссылку, но не является частью самого языка.

Программное обеспечение Oracle JDK содержит компилятор из исходного кода, написанного на языке программирования Java, в набор инструкций виртуальной машины Java.

В компиляторе языка программирования Java™ , мы можем найти такое же объяснение:

Компилятор языка программирования Java, javac, читает исходные файлы, написанные на языке программирования Java, и компилирует их в файлы классов байт-кода. При желании компилятор также может обрабатывать аннотации, найденные в исходных файлах и файлах классов, с помощью подключаемого API обработки аннотаций. Компилятор — это инструмент командной строки, но его также можно вызвать с помощью Java Compiler API. Компилятор принимает исходный код, определенный спецификацией языка Java (JLS), и создает файлы классов, определенные спецификацией виртуальной машины Java (JVMS).

Таким образом, команда JAVAC в основном является связующим звеном между спецификациями.

  • Ввод: описание .java в JLS
  • Вывод: описание .class в JVMS.

Вы можете найти некоторую информацию, проверив Спецификация виртуальной машины Java.

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

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

Позже в этих спецификациях мы нашли больше информации о формате класса и о том, как язык был переведен в этот список инструкций.

person AxelH    schedule 29.11.2017