Содержание. Содержание.1 Содержание.2 Введение.3 Постановка задачи.4 Формат файла класса.5 Структура файла класса.5 Типы элементов Constant_pool6 Формат структуры field_info. 7 Формат структуры method_info. 7 Формат атрибута Code.8 Работа JVM.. 10 Система команд JVM.12 Синтаксис языка ассемблера для платформы Java (языка JASM).14 Тестовые примеры.18 1.18 2.19 3.20 Проектирование и реализация компилятора.25 Заключение.30 Использованная литература.31
Введение. Язык программирования Java был разработан в середине 90-х годов на основе языка Oak, предназначавшегося для программирования «прошивок» для различных электронных устройств. Однако, в отличие от своего предшественника, язык Java получил широкое распространение, прежде всего как язык, использовавшийся в программировании для сети Интернет. В настоящее время область применения Java значительно расширилась, и этот язык часто применяется и в обычном прикладном программировании. Это обусловлено такими преимуществами как кроссплатформенность и безопасность, которые обеспечиваются тем, что исходный код на Java компилируется не непосредственно в машинный код, а в, так называемый, байт-код, который интерпретируется виртуальной машиной Java (JVM). Во многих современных реализациях JVM байт-код перед выполнением преобразуется в машинные инструкции, что значительно повышает производительность, приближая ее к производительности программ, написанных на C/C++. Таким образом, Java, в современном состоянии этой технологии, сочетает преимущества интерпретируемых и компилируемых языков программирования. Спецификация, описывающая JVM, как абстрактную вычислительную машину, предоставлена компанией Sun в открытый доступ. Это позволяет создавать как собственные реализации JVM для различных платформ, так и альтернативные компиляторы, генерирующие байт-код Java, в том числе для языков программирования, отличных от Java. Большинство литературы, посвященной Java, почти не уделяет внимания устройству JVM и описывает лишь сам язык Java. Однако, в ряде случаев, знание особенностей архитектуры бывает весьма полезным. В данной работе я создал учебную программу, которая может помочь в изучении архитектуры JVM – несложный ассемблер для байт-кода Java. Постановка задачи. Требуется изучить архитектуру уровня команд платформы Java, формат файла класса Java, и написать компилятор ассемблероподобного языка, позволяющего создавать файлы классов, корректно обрабатываемые реальной JVM. Данный компилятор должен поддерживать все команды байт-кода Java и важнейшие возможности JVM. Формат файла класса. Основным форматом исполняемых файлов в архитектуре Java является формат файла класса, описанный в The JavaTM Virtual Machine Specification, изданной компанией Sun. Файл данного формата имеет имя, совпадающее с идентификатором класса (за исключением вложенных классов) и расширение .class. Структура файла класса. Файл класса имеет следующую структуру: ClassFile { } (здесь и далее u1, u2, u4 – целые числа размером 8, 16 и 32 бит с порядком байтов старший байт по младшему адресу). Рассмотрим последовательно все поля. · magic – так называемое магическое число, имеющее в шестнадцатеричной записи вид 0xCAFEBABE; · minor_version, major_version – версия формата файла, по ней определяется совместимость данного файла с конкретной версией JVM; · constant_pool_count – количество элементов в Constant_pool плюс единица; · constant_pool – область констант – массив структур переменного размера, представляющих те или иные константные значения. Обращения в область констант производятся по индексу (индексация начинается с единицы; индексы, следующие за позициями констант, представляющих числа типов long и double, не используются). Форматы констант различных видов будут рассмотрены ниже; · access_flags – комбинация битовых флагов, определяющих права доступа и некоторые другие характеристики класса: Флаг Значение Смысл ACC_PUBLIC 0x0001 Доступен из-за пределов пакета ACC_FINAL 0x0010 Запрещено наследование от данного класса ACC_SUPER 0x0020 В методах данного класса требуется использовать принятую в Java2 трактовку команды invokespecial ACC_INTERFACE 0x0200 Интерфейс (является классом специального вида) ACC_ABSTRACT 0x0400 Абстрактный класс · this_class, super_class – индексы структур в области констант, ссылающихся на данный класс и его класс-предок; · interfaces_count – число интерфейсов, реализуемых данным классом; · interfaces – массив индексов структур в области констант, ссылающихся на интерфейсы, реализуемые данным классом; · fields_count – количество полей в данном классе; · fields – массив структур field_info, описывающих поля класса. Формат структуры field_info будет рассмотрен ниже; · methods_count – количество методов; · methods – массив структур method_info, описывающих методы класса. Формат структуры mettho_info будет рассмотрен ниже. Конструкторы и статические инициализаторы представляются методами со специальными именами и ; · attributes_count – количество атрибутов класса; · attributes – массив структур-атрибутов класса (поля, методы и байт-код методов также могут иметь свои атрибуты). Каждая такая структура в начале имеет два обязательных поля, описывающих тип атрибута и его размер. К классу могут быть применены следующие стандартные атрибуты: SourceFile – указывает на файл исходного текста, из которого был получен данный файл класса, и Deprecated – класс оставлен для совместимости со старым кодом и его использование не рекомендуется. Возможно создание атрибутов нестандартных типов, но они будут игнорироваться средой выполнения. Типы элементов Constant_pool Каждый элемент сonstant_pool начинается с однобайтного поля, определяющего его тип. Размер и содержание остальной части структуры зависит от типа. Существуют следующие типы констант (элементов constant_pool): · CONSTANT_Class – указываетнакласс. Содержит индекс константы типа CONSTANT_Utf8, хранящей дескриптор класса; · CONSTANT _Fieldref – указывает на поле класса. Содержитиндексыконстанттипа CONSTANT_Class и CONSTANT_NameAndType; · CONSTANT _Methodref указывает на метод класса (не интерфейса). Содержитиндексыконстанттипа CONSTANT_Class и CONSTANT_NameAndType; · CONSTANT _InterfaceMethodref указываетнаметодинтерфейса. Содержитиндексыконстанттипа CONSTANT_Class и CONSTANT_NameAndType; · CONSTANT_String – указывает на строку, содержит индекс константы типа CONSTANT_Utf8; · CONSTANT_Integer – содержит целое 32-разрядное число; · CONSTANT_Float – содержит вещественное число одинарной точности; · CONSTANT_Long – содержит целое 64-разрядное число; · CONSTANT_Double – содержит вещественное число двойной точности; · CONSTANT_NameAndType – описывает сигнатуру и имя метода либо тип и имя поля. Содержит индексы двух констант типа CONSTANT_Utf8, хранящих соответственно имя и дескриптор типа (сигнатуры); · CONSTANT_Utf8 – содержит строку в формате Utf8 (символы Unicode представляются комбинациями от 1 до 3-х байт, причем символы с кодами, не превышающими 127, представляются одним байтом). Дескрипторы – это строки, описывающие типы и сигнатуры методов в компактном формате. Примитивные типы обозначаются одной буквой, типы массивов – открывающими квадратными скобками в количестве, равном размерности массива, перед обозначением базового типа. Классы описываются строкой, содержащей имя класса с полным путем, при этом вместо точки роль разделителя имен пакетов и класса выполняет слэш. В дескрипторах сигнатур методов в круглых скобках без разделителей перечисляются дескрипторы типов параметров; после закрывающей скобки находится дескриптор типа возвращаемого значения. Для устранения неоднозначностей при этом перед дескрипторами классов записывается буква L, а после них – точка с запятой. Например, (ILjava/lang/Object;)I – (int, Object):int (буквой I обозначается тип int). Формат структуры field_info Структура field_info имеет следующий формат: field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } Здесь: · access_flags - комбинация битовых флагов, определяющих права доступа и некоторые другие характерист ики поля: Имя флага Значение Смысл ACC_PUBLIC 0x0001 Поле объявлено как public ACC_PRIVATE 0x0002 Поле объявлено как private ACC_PROTECTED 0x0004 Поле объявлено как protected ACC_STATIC 0x0008 Поле является статическим ACC_FINAL 0x0010 Поле объявлено как final и не может быть изменено после начальной инициализации ACC_VOLATILE 0x0040 Поле объявлено как volatile ACC_TRANSIENT 0x0080 Поле объявлено как transient – не сохранятся при сериализации · name_index – индекс строковой константы-имени поля в ConstantPool; · descriptor_index – индекс строковой константы-дескриптора поля (описывает тип) в ConstantPool; · attributes_count – число атрибутов поля; · attributes – атрибуты поля. К полям могут быть применены стандартные атрибуты Deprecated (см. выше), Synthetic (поле создано компилятором и не объявлено явно в исходном тексте) и ConstantValue (инициализирующее значение для статического поля). Формат структуры method_info Структура method_info имеет следующий формат: } Здесь: · access_flags – битовые флаги, определяющие права доступа и некоторые дополнительные свойства метода: Flag Name Value Interpretation ACC_PUBLIC 0x0001 Метод объявлен как public ACC_PRIVATE 0x0002 Метод объявлен как private ACC_PROTECTED 0x0004 Метод объявлен как protected ACC_STATIC 0x0008 Метод является статическим ACC_FINAL 0x0010 Метод является финальным и не может быть замещен ACC_SYNCHRONIZED 0x0020 Метод объявлен как synchronized ACC_NATIVE 0x0100 Метод является «родным» и содержит код, непосредственно выполняющийся физическим процессором ACC_ABSTRACT 0x0400 Метод является абстрактным ACC_STRICT 0x0800 Устанавливает «строгий» режим работы с вещественными числами (только в Java 2). · name_index, descriptor_index, attributes_count – аналогично field_info; · attributes – атрибуты метода. Методы могут иметь следующие стандартные атрибуты: o Deprecated, Synthetic – аналогично соответствующим атрибутам полей; o Exceptions – описание исключений, которые может генерировать метод. Нужно отметить, что обязательное описание исключений не является необходимым требованием для корректного выполнения; o Code – собственно говоря, байт-код метода. Формат атрибута Code. Атрибут Code имеет следующую структуру: Code _ attribute { u2 attribute_name_index; } Здесь: · attribute_name_index, attribute_length – стандартные для любого атрибута поля, описывающие его тип и размер; · max_stack – предельный размер стека операндов для метода; · max_locals – предельное количество локальных переменных метода (включая формальные параметры); · code_length – размер байт-кода метода в байтах; · code – собственно говоря, байт-код; · exception_table_length – количество защищенных блоков; · exception_table – таблица защищенных блоков (обработчиков исключений). Каждая ее запись имеет следующие поля: o start_pc – индекс начала защищенного блока в массиве байт-кода, o end_pc – индекс конца защищенного блока, o handler_pc – индекс начала обработчика, o catch_type – тип обрабатываемого исключения (индекс в ConstantPool) или 0 для блока try ... finally; · attributes_count – числоатрибутов; · attributes – атрибуты кода метода. Могут использоваться стандартные атрибуты LineNumberTable и LocalVariableTable, содержащие отладочную информацию. Работа JVM При запуске JVM в качестве параметров ей передаются имя класса, с метода main которого будет начато выполнение программы, а также аргументы командной строки программы. Вначале загружается указанный класс. Другие классы, используемые в программе, загружаются при первом обращении к ним. Процесс загрузки класса состоит из нескольких этапов: · собственно загрузка файла класса (loading). По умолчанию осуществляется с помощью класса ClassLoader из стандартной библиотеки Java, однако можно использовать пользовательский загрузчик для изменения способа поиска файла; · связывание (linking). Состоит из трех стадий: o проверка (verification) на правильность формата файла класса и корректность байт-кода (например, на отсутствие переходов на середину инструкции), o подготовка (preparation) – выделение памяти для статических полей класса и заполнение их нулевыми значениями, o разрешение имен (resolution) ; · инициализация (initialization) статических данных начальными значениями. Включает вызов метода , если он присутствует в классе. Программа, выполняемая JVM, может иметь несколько потоков выполнения. Реализация многопоточности зависит от используемого аппаратного обеспечения и может быть различной – разные потоки могут выполняться на разных процессорах или им могут выделяться кванты времени на одном процессоре. JVM имеет ряд средств для синхронизации работы потоков и защиты разделяемых ими данных. Важнейшим из них является механизм блокировок (locks), поддерживаемый на уровне системы команд JVM. Каждый объект имеет ассоциированный с ним «замок» (lock). Если один из потоков «закрыл» этот «замок», то ни один другой поток не сможет также его «закрыть» до тех пор, пока первый поток его не «откроет». JVM определяет несколько виртуальных областей памяти, которые она использует при своей работе: · регистр PC (programcounter), указывающий на текущую позицию выполнения в методе. Каждый поток программы имеет свой регистр PC; · стек. Каждый поток имеет свой собственный стек. При входе в метод на вершине стека создается фрейм, содержащий локальные переменные метода и его стек операндов. Размер именно этих областей указывается полями max_locals и max_stack атрибута метода Code; · куча – область памяти, в которой динамически размещаются объекты классов и массивы. Память из-под не используемых более объектов (на которые нет ссылок) автоматически освобождается так называемым сборщиком мусора; · область методов. В нее при загрузке классов помещаются байт-код методов, различная информация о методах и полях. Область методов также содержит области констант времени выполнения, которые хранят содержимое constantpool из загруженных классов; · стеки для native-методов. Расположение и представление этих областей в физической памяти может быть различным в различных реализациях JVM. JVM является стековой машиной. Большинство из команд JVM выполняют одно из следующих действий: · считывают значение из переменной или поля и помещают его на вершину стека, · сохраняют значение с вершины стека в переменной или поле, · выполняют те или иные действия над значениями, взятыми с вершины стека, и записывают результирующее значение (если оно есть) на вершину стека, · выполняют переход на команду с заданным смещением относительно текущего значения регистра PC безусловно или в зависимости от значений, прочитанных с вершины стека. Любое чтение из стека операндов приводит к удалению из него прочитанного значения. Размер стека операндов, указываемый как max_stack, рассчитывается следующим образом: значения типов long и double занимают две ячейки стека (8 байт), любые другие значения – одну (4 байта). Значения типов char, boolean, byte, short сохраняются в одной четырехбайтной ячейке. Тут можно отметить, что в подавляющем большинстве случаев JVM не делает различий между логическими значениями и целыми числами типа int, для среды выполнения не существует отдельного булевского типа (лжи соответствует нулевое значение, истине – ненулевое, как правило, единица). Однако, в массивах типа boolean[] на каждый элемент выделяется один байт. Существует следующее ограничение на байт-код: каждый раз, когда точка выполнения достигает любой конкретной позиции в методе, глубина стека должна быть одинаковой, кроме того, тип верхних значений в стеке должен соответствовать требуемому типу извлекаемых очередной командой значений. В области локальных переменных на момент начала выполнения метода в первых позициях находятся фактические параметры метода, а в случае метода экземпляра первую (нулевую) позицию занимает ссылка this на текущий объект. Никакого различия в процессе выполнения метода между параметрами (даже ссылкой this) и, собственно говоря, локальными переменными не делается. Так же как и в стеке, значения типа long и double в области локальных переменных занимают две четырехбайтные ячейки, значения типов размером менее 32-х разрядов расширяются до четырех байт. В корректном байт-коде должны выполняться, в частности, следующие условия: во-первых, типы значений в локальных переменных должны соответствовать требуемым для команд, которые обращаются к этим переменным, во-вторых, не допускается чтение значения переменной до ее инициализации (присвоения значения). Перед вызовом метода его фактические параметры должны находиться на вершине стека; они становятся операндами соответствующей команды вызова. При возврате из метода, за исключением методов, возвращающих void, возвращаемое значение помещается на вершину стека. В процессе выполнения программы в результате возникновения той или иной ошибки либо выполнения команды athrow может быть сгенерировано исключение. При этом происходит поиск подходящего обработчика исключения (защищенного блока) в текущем методе, если он не найден, то в методе, вызвавшем текущий и т. д. Если подходящий обработчик найден, то управление передается в точку, определяемую полем handler_pc соответствующей записи таблицы exception_table в атрибуте Code метода. Ссылка на объект исключения при этом помещается на вершину стека. Объект исключения обязательно должен принадлежать классу Throwable или классу, производному от него.
Курсовые работы по информатикеСодержание. Содержание.1 Содержание.2 Введение.3 Постановка задачи.4 Формат файла класса.5 Структура файла класса.5 Типы элементов Constant_pool6
Оценок: 310 (Средняя 5 из 5)
Специалисты RetsCorp работают в digital-сфере более 7 лет. За это время мы разработали более 500+ успешных проектов. Основываясь на своем опыте и знании рынка, мы с уверенностью можем сказать, что будет работать, а что — нет. Заказывая создание лендинга для бизнеса в нашей студии, вы получаете работающие решения, необходимые именно вашему бизнесу.
Сотрудничая с нами, вы будете не клиентом, а нашим партнером. Благодаря этому мы будем развивать ваш бизнес как собственный. Мы так же как и вы заинтересованы в успехе проекта, поскольку ваша успешность будет нашей рекламой.