байт-код класса, на этот раз я вижу вас насквозь!

Java

Введение

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

Скомпилированный файл класса представляет собой файл двоичного потока, такой как следующий класс:

public class ServiceResult<T> {

    private static final int SUCCESS_CODE = 200;
    private static final String SUCCESS_MESSAGE = "Success";

    private int code;
    private String message;
    private T data;

    public ServiceResult(T data) {
        this.code = SUCCESS_CODE;
        this.message = SUCCESS_MESSAGE;
        this.data = data;
    }

    public ServiceResult(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public boolean isSuccess() {
        return code == SUCCESS_CODE;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public T getData() {
        return data;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("ServiceResult{");
        sb.append("code=").append(code);
        sb.append(", message='").append(message).append('\'');
        sb.append(", data=").append(data);
        sb.append('}');
        return sb.toString();
    }
}

Скомпилированный класс открывается в шестнадцатеричном формате следующим образом:

Примечание. Файл класса представлен в байтах (8 бит), а u1, u2, u4 и u8 используются для представления 1 байта, 2 байтов, 4 байтов и 8 байтов чисел без знака в форме Big-edian, то есть , сначала старший байт.

Структура класса

Если бинарный файл класса описывает свою логическую структуру в виде C-подобной языковой структуры, она будет такой, как показано на следующем рисунке:

Как видно из рисунка, файл класса в основном содержит магию, минорную версию, мажорную версию, постоянный пул, флаги доступа, this_class, суперкласс, интерфейсы, поля, методы, атрибуты 11 частей, каждая часть компактно склеена вместе , Здесь нет разделения разделителями, и каждая структура описана отдельно ниже.

Прежде чем приступить к представлению каждой структуры, необходимо пояснить, что эта статья основана на jvm1.8.

Эта статья немного длинная,здесьТипографика выглядит более удобной

1. magic

Магическое число:Беззнаковое число из 4 байтов с фиксированным значением 0xCAFEBABE, используемое для идентификации файла как файла класса.

2. minor version

Второстепенный номер версии:Беззнаковое число, занимающее два байта, в диапазоне от 0 до 65535. Вместе с мажорной версией указывает версию текущего файла класса.jvm может быть совместим вперед с предыдущей версией, но не совместим обратно, то есть jdk7 виртуальная машина не может запустить компиляцию jdk8.класс

3. major version

Номер основной версии:Число без знака, занимающее два байта. Основной номер версии, используемый jdk1.1, — 45, и каждая основная версия увеличивается на 1. Например, jdk1.8 — 52.

4. constant pool

Постоянный пул:Пул констант — очень важная часть класса, в нем хранятся не только константы, определенные в классе, но и различные метаданные в файле класса, включая некоторые строки, имена классов, имена интерфейсов, имена полей и методы. , и т. д., на его функцию следует ссылаться, часть пула констант сначала имеет два байта u2 для записи количества содержащихся в нем констант.

PS1: Константный пул представляет собой массив констант. Его нижний индекс начинается с 1, то есть эффективный размер - это Constant_pool_count-1, а 0-й элемент недействителен. Некоторые структуры могут использовать индекс 0, чтобы указать, что нет ссылки на постоянный.

PS2: дизайн пула констант эффективно уменьшает размер файла класса, подумайте о тех именах классов, которые используются повторно, строка теперь должна хранить только одну копию, а в качестве ссылки нужно использовать только u2 для сохранения своего индекса в постоянный бассейн просто отлично

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

Постоянные теги включают CONSTANT_Utf8, CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double, CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref, CONSTANT_NameAndType, CONSTANT_MethodHandle, CONSTANT_MethodType, CONSTANT_InvokeDynamic.

4.1 CONSTANT_Utf8_info

Самая основная константа в пуле констант, используемая для сохранения строки в кодировке utf8, такой как строка константы, имя класса, имя поля, имя метода и т. д. Значение является ссылкой (индексом) на нее.

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

tag=1, length представляет длину строки в байтах, например, length=20 означает, что следующие 20 байтов представляют собой строку в кодировке utf8.

Вот два дополнительных момента:

  • java использует переменную кодировку utf8: символы ASCII ('\u0001' ~ '\u007F', то есть 1~127) представлен 1 байтом, ноль ('\u0000')а также '\u0080' прибыть '\u07FF' Символы между ними представлены 2 байтами, '\u0800' прибыть '\uFFFFСимволы между ' представлены 3 байтами.

    Наоборот, если старший бит байта равен 0, это однобайтовый символ.

    Старшие 3 бита прочитанного байта110Это двухбайтовый символ, за которым следует еще 1 байт.

    Старшие 4 бита прочитанного байта1110, представляет собой трехбайтовый символ, за которым следуют еще 2 байта.

    О том, как декодировать, вы можете проверить в официальной документации.В java нам нужно использовать толькоnew String(bytes, StandardCharset.UTF8)чтобы получить декодированную строку

  • длина представлена ​​как u2 (0-65535), тогда максимальная длина строки, представленной им, равна 65535

4.2 CONSTANT_Integer_info
CONSTANT_Integer_info {
    u1 tag;
    u4 bytes;
}

int, tag=3, следующие 4 байта представляют собой значение int. Добавьте следующие пункты о CONSTANT_Integer:

  • с обратным порядком байтов, сначала старший байт, то же верно и ниже

    Если вы разберете его самостоятельно, это будет выглядеть так:

    int value = 0;
    byte[] data = new byte[4];
    is.read(data);
    value = (value | (((int) data[0]) & 0xff)) << Byte.SIZE * 3;
    value = (value | (((int) data[1]) & 0xff)) << Byte.SIZE * 2;
    value = (value | (((int) data[2]) & 0xff)) << Byte.SIZE;
    value = (value | (((int) data[3]) & 0xff));
    

    Мы можем прочитать значение int, используя метод readInt() класса DataInputStream.

  • Джаваshort, char, byte, booleanИспользуйте int для представления, логический массив представлен массивом байтов (1 байт представляет 1 логический элемент)

4.3 CONSTANT_Float_info
CONSTANT_Float_info {
    u1 tag;
    u4 bytes;
}

float число с плавающей запятой, tag=4, следующие 4 байта представляют его значение, которое определено стандартом IEEE 754. Значение с плавающей запятой можно прочитать с помощью метода readFloat() класса DataInputStream.

4.4 CONSTANT_Long_info
CONSTANT_Long_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

tag=5, long integer, long и double хранятся в классе двумя частями (старшие 4 байта, позиция 4 байта). Значение с плавающей запятой можно прочитать с помощью метода readLong() класса DataInputStream.

4.5 CONSTANT_Double_info
CONSTANT_Double_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

tag=6, число двойной точности с плавающей запятой, определенное стандартом IEEE 754. Хранилище такое же, как CONSTANT_Long.

4.6 CONSTANT_Class_info
CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
}

tag=7, указывающий на класс или интерфейс, обратите внимание, что это не тип поля или тип параметра и тип возвращаемого значения метода. name_index — это постоянный индекс пула, и константа в этом индексе должна бытьCONSTANT_Utf8_info

4.7 CONSTANT_String_info
CONSTANT_String_info {
    u1 tag;
    u2 string_index;
}

tag=8, что указывает на константную строку, string_index — это индекс пула констант, константа по этому индексу должна бытьCONSTANT_Utf8_info, в котором хранится значение строки

4.8 CONSTANT_Fieldref_info
CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

tag=9, указывает информацию о ссылочном поле, включая статическое поле и поле экземпляра.

class_index — это индекс константы типа CONSTANT_Class_info (класс/интерфейс) в пуле констант, указывающий класс, к которому принадлежит поле. name_and_type_index — постоянный индекс типа CONSTANT_NameAndType_info (см. ниже) в пуле констант, указывающий имя и тип поля.

Объясните ссылку на поле, включая следующий метод, ссылка на метод интерфейса такая же:

  • Начиная с этой статьи класс ServiceResultcodeВозьмем поле в качестве примера, код используется в нескольких методах.По сравнению с сохранением нескольких копий информации о поле, очевидно, более целесообразно сохранить одну копию информации о поле в пуле констант, а затем сохранить ее индекс в других местах, где Это использовано.
  • CONSTANT_Fieldref_info предназначена для извлечения полей (которые могут относиться к этому классу или внешним классам), на которые есть ссылки в коде, в константы, которые аналогичны описанным ниже.field_infoне путай
4.9 CONSTANT_Methodref_info
CONSTANT_Methodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

tag=10, что означает информацию об эталонном методе, включая статический метод и метод экземпляра.

class_index — это индекс константы типа CONSTANT_Class_info (здесь может быть только класс) в пуле констант, указывающий класс, к которому принадлежит метод. name_and_type_index — постоянный индекс типа CONSTANT_NameAndType_info в пуле констант, указывающий имя и параметры метода, а также информацию о возвращаемом значении.

4.10 CONSTANT_InterfaceMethodref_info
CONSTANT_InterfaceMethodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

tag=11, указывающий информацию о методе интерфейса.

class_index — это индекс константы типа CONSTANT_Class_info (здесь может быть только интерфейс) в пуле констант, указывающий интерфейс, которому принадлежит метод. name_and_type_index совпадает с CONSTANT_Methodref_info.

4.11 CONSTANT_NameAndType_info
CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
}

tag=12, который хранит имя, тип и другую информацию о поле или методе.Видно, что это снова две ссылки. name_index указывает на CONSTANT_Utf8_info, указывающее поле или метод.неполное имя. descriptor_index также указывает на CONSTANT_Utf8_info, которая представляет информацию описания этого поля/метода.

Descriptor

Дескриптор хранится в виде строки CONSTANT_Utf8_info.

  • дескриптор поля (FieldType), FieldType может быть примитивным типом:B(byte) C(char) D(double) F(float) I(int) J(long) S(short) Z(boolean), тип объекта: L+ полное имя класса, тип массива: [+ тип элемента

    int a; // I
    Integer b; //Ljava/lang/Integer
    double[] c; //[D
    double[][] d; //[[D
    Object[] e; //[Ljava/lang/Object
    Object[][][] f; //[[[Ljava/lang/Object
    
  • дескриптор метода (MethodDescriptor), формат MethodDescriptor(参数类型)返回类型

    /**
     * 描述符:(IDLjava/lang/Thread;)Ljava/lang/Object;
     */
    Object m(int i, double d, Thread t) {...}
    
4.12 CONSTANT_MethodHandle_info
CONSTANT_MethodHandle_info {
    u1 tag;
    u1 reference_kind;
    u2 reference_index;
}

tag=15, дескриптор метода, такой как получение статического поля класса, поля экземпляра, вызов метода, конструктора и т. д., будет преобразован в ссылку на дескриптор.

  • reference_kind

    Kind Description Interpretation
    1 REF_getField getfield C.f:T
    2 REF_getStatic getstatic C.f:T
    3 REF_putField putfield C.f:T
    4 REF_putStatic putstatic C.f:T
    5 REF_invokeVirtual invokevirtual C.m:(A*)T
    6 REF_invokeStatic invokestatic C.m:(A*)T
    7 REF_invokeSpecial invokespecial C.m:(A*)T
    8 REF_newInvokeSpecial new C; dup; invokespecial C.<init>:(A*)V
    9 REF_invokeInterface invokeinterface C.m:(A*)T

    f: поле, m: метод, : конструктор экземпляра

  • reference_index

    • Для Kind=1, 2, 3, 4 reference_index ссылается на CONSTANT_Fieldref_info
    • Для типов = 5, 6, 7, 8, reference_index ссылается на CONSTANT_Methodref_info.
    • Для Kind=9 reference_index ссылается на CONSTANT_InterfaceMethodref_info.
4.13 CONSTANT_MethodType_info
CONSTANT_MethodType_info {
    u1 tag;
    u2 descriptor_index;
}

tag=16, описывающий тип метода. descriptor_index относится к CONSTANT_Utf8_info, представляющему дескриптор метода

4.14 CONSTANT_InvokeDynamic_info
CONSTANT_InvokeDynamic_info {
    u1 tag;
    u2 bootstrap_method_attr_index;
    u2 name_and_type_index;
}

tag=18, справочная информация об инструкциях динамического вызова invokedynamic.

  • bootstrap_method_attr_index, индекс массива bootstrap_methods[] в атрибуте BootstrapMethods, каждый метод начальной загрузки ссылается на CONSTANT_MethodHandle_info
  • name_and_type_index, ссылающийся на константу CONSTANT_NameAndType_info
5. access flags

Флаги доступа представляют информацию об управлении доступом и оформлении для классов, интерфейсов, полей и методов.

Access Flag(u2) Value Объект действия
ACC_PUBLIC 0x0001 class, inner, field, method
ACC_PRIVATE 0x0002 inner, field, method
ACC_PROTECTED 0x0004 inner, field, method
ACC_STATIC 0x0008 inner, field, method
ACC_FINAL 0x0010 class, inner, field, method
ACC_SUPER 0x0020 class
ACC_SYNCHRONIZED 0x0020 method
ACC_VOLATILE 0x0040 field
ACC_BRIDGE 0x0040 method
ACC_TRANSIENT 0x0080 field
ACC_VARARGS 0x0080 method
ACC_NATIVE 0x0100 method
ACC_INTERFACE 0x0200 class, inner
ACC_ABSTRACT 0x0400 class, inner, method
ACC_STRICT 0x0800 method
ACC_SYNTHETIC 0x1000 class, inner, field, method
ACC_ANNOTATION 0x2000 class, inner
ACC_ENUM 0x4000 class, inner, field

Большинство из них можно увидеть по названию, а также добавлены следующие пункты:

  • ACC_SUPER: метод суперкласса для вызова специальной инструкции, требующей специальной обработки.
  • ACC_BRIDGE: флаг метода моста, метод с этим флагом также имеет флаг ACC_SYNTHETIC
  • ACC_STRICT: strictfp, строгий формат с плавающей запятой, метод использует FP-строгий формат с плавающей запятой.
  • ACC_SYNTHETIC: флаг генерируется компилятором, а не исходным кодом.
6. this class

Текущий класс или интерфейс, указывающий на константу CONSTANT_Class_info, из которой может быть разрешено полное имя текущего класса. уровень имени пакета/разделить вместо.,какjava/lang/Object.

7. super class

Прямой индекс родительского класса текущего класса, указывающий на константу CONSTANT_Class_info, super_class=0, когда прямого родительского класса нет.

8. interfaces

Во-первых, используйте u2, чтобы указать количество n прямых родительских интерфейсов текущего класса или интерфейса. Массив, состоящий из n u2, является индексом этих родительских интерфейсов в пуле констант, типом является CONSTANT_Class_info, слева направо в порядке объявления.

9. fields
field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

field_info сохраняет информацию о полях текущего класса. Очень просто, большинство из них упоминалось ранее, а атрибуты объясняются в Разделе 11 ниже. Следует отметить, что поля содержат только поля текущего класса, например, поле c внутреннего класса B класса A относится к классу A$B.

10. methods
method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

Сохраните информацию о методе текущего класса, как и field_info

11. attributes

Таблица атрибутов: атрибуты существуют сClassFile, field_info, method_infoКроме того, атрибут Code также содержит информацию о вложенных атрибутах.Атрибуты используются для описания такой информации, как коды инструкций, исключения, аннотации, дженерики и т. д. В JLS8 предопределены 23 атрибута, каждый из которых имеет различную структуру (переменную длину), но может абстрагироваться в следующую общую структуру.

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

attribute_name_index: это индекс имени атрибута в пуле констант, по которому текущий атрибут может быть определен, к какому конкретному типу он принадлежит, например, «Code» означает, что в данный момент это Code_attribute

attribute_length: Указывает, сколько байтов составляет информация о содержимом атрибута. Java позволяет настраивать новые атрибуты. Если jvm не знает этого, он будет напрямую читать байты attribute_length в соответствии с общей структурой.

23 атрибута можно разделить на 3 группы в зависимости от их функций:

  • Используется переводом jvm: ConstantValue, Code, StackMapTable, Exceptions, BootstrapMethods.
  • Используется анализом библиотеки классов Java: InnerClasses, EnclosingMethod, Synthetic, Signature, RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations, RuntimeVisibleParameterAnnotations/RuntimeInvisibleParameterAnnotations, RuntimeVisibleTypeAnnotations/RuntimeInvisibleTypeAnnotations, AnnotationDefault, MethodParameters
  • Ни синтаксический анализ jvm, ни синтаксический анализ библиотеки классов java не требуется для таких сценариев, как инструменты отладки: SourceFile, SourceDebugExtension, LineNumberTable, LocalVariableTable, LocalVariableTypeTable, Deprecated

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

11.1 ConstantValue
ConstantValue_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 constantvalue_index;
}

Существует в field_info и представляет постоянное значение, напримерprivate final int x = 5середина5. Значением, на которое ссылается attribute_name_index, является «ConstantValue», attribute_length фиксируется равным 2, а Constantvalue_index следующих двух байтов является индексом постоянного значения в пуле констант, который является одним из CONSTANT_Long, CONSTANT_Float, CONSTANT_Double, CONSTANT_Integer и CONSTANT_String. .

11.2 Code
Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length;
    {   u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

Описывает инструкции байт-кода после компиляции тела метода. Метод, описанный ранееmethod_infoструктура, а информация о теле метода существует в атрибуте кода в его таблице атрибутов. Если это абстрактный метод, у него нет этого свойства.

Я говорил об общей структуре атрибутов ранееattribute_infoуже сказал когдаattribute_name_index, attribute_length, который доступен для каждого атрибута, и не будет объясняться ниже, будут представлены только другие части.

  • max_stack , максимальная глубина стека операндов, используемая для выделения размера стека

  • max_locals — максимальная емкость таблицы локальных переменных в кадре стека методов, в которой хранятся локальные переменные, параметры методов, параметры исключений и т. д. Возьмите слот в качестве единицы, выделите 1 слот для переменных в пределах 32 бит и выделите 2 слота для переменных больше 32 бит. Например, long и double выделяют 2 слота. Обратите внимание, что объекты хранятся как ссылки. Также обратите внимание, что для методов экземпляра указатель объекта this передается по умолчанию, поэтому минимальное значение max_locals в настоящее время равно 1.

  • code[code_length], хранит список инструкций байт-кода, каждая инструкция байт-кода представляет собой байт, так что 8 бит может представлять до 256 различных инструкций.Следует отметить, что этот массив байт-потока хранит не все инструкции, некоторые инструкции. соответствующие операнды, пропустить соответствующие n-байтовые операнды, а затем следующую инструкцию.Я продемонстрирую подробности в другой статье.

  • exception_table[exception_table_length], таблица исключений метода, обратите внимание, что это не исключение, вызванное объявлением метода, а исключение try-catch, и исключение каждого улова является элементом таблицы exception_table.

    • catch_type, тип перехватываемого исключения, указывает на константу CONSTANT_Class_info.
    • start_pc, смещение инструкции байт-кода относительно начала метода, эквивалентно индексу в code[code_length]
    • end_pc, смещение инструкции байт-кода относительно начала метода, эквивалентное индексу в code[code_length]
    • handler_pc, смещение инструкции байт-кода относительно начала метода, эквивалентное индексу в code[code_length]

    Эти элементы означают, что если в интервале [start_pc, end_pc) возникает исключение типа catch_type или его подкласса (catch_type=0 означает перехватывать любое исключение), перейти к инструкции в handler_pc для продолжения выполнения.

    Добавьте три пункта:

    1) Способ использования инструкций в блоке finaly состоит в том, чтобы иметь избыточную копию в каждой ветви кода.

    2) Для исключений, которые не отображаются пойманными, затем передайтеathrowИнструкция продолжает кидать

    3) Хотя длина инструкции code_length равна u4, start_pc, end_pc и handler_pc являются только 2-байтовыми беззнаковыми числами u2, а максимальный диапазон представления составляет всего 65535, поэтому метод может иметь только до 65535 инструкций (каждая инструкция не имеет операции). количество)

  • attribute[attributes_count], список вложенных атрибутов

11.3 StackMapTable
StackMapTable_attribute {
    u2              attribute_name_index;
    u4              attribute_length;
    u2              number_of_entries;
    stack_map_frame entries[number_of_entries];
}

Как упоминалось выше, Code_attribute также может содержать таблицы атрибутов, StackMapTable находится в таблице атрибутов атрибутов Code и добавляется для проверки вывода типа на этапе проверки байт-кода jvm.

11.4 Exceptions
Exceptions_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 number_of_exceptions;
    u2 exception_index_table[number_of_exceptions];
}

выразить черезthrowsОбъявленные исключения, которые могут быть выброшены, структура очень проста.Каждый элемент exception_index_table u2 указывает на константу CONSTANT_Class_info

11.5 BootstrapMethods
BootstrapMethods_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 num_bootstrap_methods;
    {   u2 bootstrap_method_ref;
        u2 num_bootstrap_arguments;
        u2 bootstrap_arguments[num_bootstrap_arguments];
    } bootstrap_methods[num_bootstrap_methods];
}

Находится в ClassFile, содержит метод начальной загрузки, на который ссылается инструкция invokedynamic.

  • bootstrap_method_ref, ссылается на константу CONSTANT_MethodHandle_info, reference_kind MethodHandle должен быть REF_invokeStatic или REF_newInvokeSpecial.
  • num_bootstrap_arguments, список параметров метода начальной загрузки, каждый элемент в массиве являетсяCONSTANT_String_info, CONSTANT_Class_info, CONSTANT_Integer_info, CONSTANT_Long_info, CONSTANT_Float_info, CONSTANT_Double_info, CONSTANT_MethodHandle_info, or CONSTANT_MethodType_infoЦитировать
11.6 InnerClasses
InnerClasses_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 number_of_classes;
    {   u2 inner_class_info_index;
        u2 outer_class_info_index;
        u2 inner_name_index;
        u2 inner_class_access_flags;
    } classes[number_of_classes];
}

Запишите информацию о внутреннем классе, классы — это список внутренних классов текущего класса, где inner_class_info_index, external_class_info_index указывают на константы типа CONSTANT_Class, представляющие ссылку на информацию о внутреннем классе и внешнем классе соответственно, inner_name_index — это ссылка на имя внутреннего класса (CONSTANT_Utf8_info ), равный 0, означает анонимный внутренний класс, inner_class_access_flags — это флаг доступа к внутреннему классу, такой же, как и access_flags

11.7 EnclosingMethod
EnclosingMethod_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 class_index;
    u2 method_index;
}

Он находится в структуре ClassFile и хранит информацию о локальном или анонимном классе.

  • class_index, ссылка на класс, который непосредственно его содержит, ссылается на константу CONSTANT_Class_info, представляющую самый внутренний класс, содержащий текущее объявление класса.
  • method_index относится к константе CONSTANT_NameAndType_info, которая непосредственно содержит имя и тип метода локального класса и анонимного класса.
11.8 Synthetic
Synthetic_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
}

Отмечает, генерируются ли компилятором классы, методы и поля, что является синонимом ACC_SYNTHETIC, attribute_length=0, и наличие этого атрибута указывает на true.

11.9 Signature
Signature_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 signature_index;
}

Существует в таблице свойств классов, методов и полей и используется для хранения общей информации о классах, методах и полях (переменные типа — переменные типа, параметризованные типы — параметризованные типы).

О дженериках можно обратиться кздесь

  • signal_index, который ссылается на константу CONSTANT_Utf8_info, представляющую подпись
11.10 RuntimeVisibleAnnotations
RuntimeVisibleAnnotations_attribute {
    u2         attribute_name_index;
    u4         attribute_length;
    u2         num_annotations;
    annotation annotations[num_annotations];
}

Существует в классах, методах, полях и хранит информацию об аннотациях, видимую во время выполнения (RetentionPolicy.RUNTIME), которую можно получить с помощью API отражения.здесь

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

11.11 RuntimeInvisibleAnnotations
RuntimeInvisibleAnnotations_attribute {
    u2         attribute_name_index;
    u4         attribute_length;
    u2         num_annotations;
    annotation annotations[num_annotations];
}

Имеет ту же структуру, что и RuntimeVisibleAnnotations, но является невидимым, то есть не может быть получен API отражения.В настоящее время jvm игнорирует это свойство.

11.12 RuntimeVisibleParameterAnnotations
RuntimeVisibleParameterAnnotations_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 num_parameters;
    {   u2         num_annotations;
        annotation annotations[num_annotations];
    } parameter_annotations[num_parameters];
}

Он существует в таблице атрибутов method_info и хранит информацию об аннотациях параметров метода, видимых во время выполнения.По сравнению с RuntimeVisibleAnnotations обнаружено, что RuntimeVisibleParameterAnnotations хранит аннотации каждого параметра в списке параметров метода (эквивалентно набору RuntimeVisibleParameterAnnotations). , дескрипторы порядка и метода Параметры в том же порядке

11.13 RuntimeInvisibleParameterAnnotations
RuntimeInvisibleParameterAnnotations_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 num_parameters;
    {   u2         num_annotations;
        annotation annotations[num_annotations];
    } parameter_annotations[num_parameters];
}

я не хочу больше говорить

11.14 RuntimeVisibleTypeAnnotations
RuntimeVisibleTypeAnnotations_attribute {
    u2              attribute_name_index;
    u4              attribute_length;
    u2              num_annotations;
    type_annotation annotations[num_annotations];
}

Существовать в таблице атрибутов class_file, method_info, field_info, code, new in java8. JLS8 добавляет два новых типа элементов (ElementType.TYPE_PARAMETER, ElementType.TYPE_USE), и соответствующие атрибуты аннотаций, используемые для описания, также были изменены соответствующим образом. С помощью этого атрибута type_annotation хранит информацию аннотаций и свой функциональный объект.

11.15 RuntimeInvisibleTypeAnnotations
RuntimeInvisibleTypeAnnotations_attribute {
    u2              attribute_name_index;
    u4              attribute_length;
    u2              num_annotations;
    type_annotation annotations[num_annotations];
}

немного. . .

11.16 AnnotationDefault
AnnotationDefault_attribute {
    u2            attribute_name_index;
    u4            attribute_length;
    element_value default_value;
}

Существовать вmethod_infoлист свойств, в котором записаны значения по умолчанию для элементов аннотации

11.17 MethodParameters
MethodParameters_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 parameters_count;
    {   u2 name_index;
        u2 access_flags;
    } parameters[parameters_count];
}

Существовать вmethod_infoТаблица атрибутов, информация о параметрах метода записи, имя параметра name_index, флаги доступа имеют ACC_FINAL, ACC_SYNTHETIC, ACC_MANDATED

11.18 SourceFile
SourceFile_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 sourcefile_index;
}

В таблице атрибутов class_file запишите имя файла, сгенерировавшего файл. Стек исключений может отображать эту информацию, которая обычно совпадает с именем класса, но не с внутренним классом. Это необязательный атрибут, который означает, что компилятор не обязан генерировать эту информацию.

11.19 SourceDebugExtension
SourceDebugExtension_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 debug_extension[attribute_length];
}

Существует в структуре класса, необязателен, сохраняет расширенную отладочную информацию для языков, отличных от Java.debug_extensionМассив является индексом в CONSTAN_Utf8_info.

11.20 LineNumberTable
LineNumberTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;
    {   u2 start_pc;
        u2 line_number;	
    } line_number_table[line_number_table_length];
}

В таблице атрибутов кода хранится отношение сопоставления между номером строки исходного кода и смещением байт-кода (первая инструкция метода), смещение байт-кода start_pc, номер строки исходного кода line_number, необязательный.

Вопрос: Как распечатать номер строки исходного кода ошибки в стеке ошибок? Как поддерживать отладку точки останова в исходном коде?

11.21 LocalVariableTable
LocalVariableTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_table_length;
    {   u2 start_pc;
        u2 length;
        u2 name_index;
        u2 descriptor_index;
        u2 index;
    } local_variable_table[local_variable_table_length];
}

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

11.22 LocalVariableTypeTable
LocalVariableTypeTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_type_table_length;
    {   u2 start_pc;
        u2 length;
        u2 name_index;
        u2 signature_index;
        u2 index;
    } local_variable_type_table[local_variable_type_table_length];
}

В таблице атрибутов кода, подобно LocalVariableTable, signal_index также относится кCONSTANT_Utf8_infoКонстанты, соответствующие переменным, содержащим дженерики, будут храниться как в LocalVariableTable, так и в LocalVariableTypeTable.

11.23 Deprecated
Deprecated_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
}

Класс, метод, маркер окончания срока действия поля, без дополнительной информации, attribute_length=0, если этот атрибут появляется, значит, добавлена ​​аннотация @deprecated

над!Если вы считаете, что написать это нормально, пожалуйста, поставьте лайк, чтобы поощрить это!


Следующее уведомление: начните писать программу, которая анализирует файлы классов (байт-код)

Обратите внимание на WeChat, вас ждет еще больше интересного