Heim >Java >javaLernprogramm >Beispiel einer Methode zum Implementieren eines Klassenparsers in Java
In diesem Artikel werden hauptsächlich Beispiele für Java-Klassenparser-Implementierungsmethoden durch die Analyse von Klassendateien vorgestellt. Es hat einen gewissen Referenzwert und Freunde, die es brauchen, können mehr darüber erfahren.
Kürzlich schreibe ich ein privates Projekt namens ClassAnalyzer. Der Zweck von ClassAnalyzer besteht darin, uns ein tiefgreifendes Verständnis des Designs und der Struktur von Java-Klassendateien zu vermitteln. Das Hauptgerüst und die Grundfunktionen wurden fertiggestellt und einige detaillierte Funktionen werden in Zukunft hinzugefügt. Tatsächlich stellt JDK bereits das Befehlszeilentool javap zum Dekompilieren von Klassendateien bereit, aber dieser Artikel wird meine Idee der Implementierung des Parsers klären.
Klassendatei
Als Träger von Klassen- oder Schnittstelleninformationen definiert jede Klassendatei vollständig eine Klasse. Damit Java-Programme „einmal geschrieben und überall ausgeführt werden“ können, enthält die Java Virtual Machine-Spezifikation strenge Vorschriften für Klassendateien. Die grundlegende Dateneinheit, aus der eine Klassendatei besteht, sind Bytes. Zwischen diesen Bytes gibt es keine Trennzeichen. Dadurch werden in der gesamten Klassendatei fast alle für den Programmbetrieb erforderlichen Daten dargestellt multiple Dargestellt durch aufeinanderfolgende Bytes.
Gemäß der Java Virtual Machine-Spezifikation verwendet die Klassendatei eine Pseudostruktur, die der C-Sprachstruktur ähnelt, um Daten zu speichern. In dieser Pseudostruktur gibt es nur zwei Datentypen: vorzeichenlose Zahlen und Tische. Die Java Virtual Machine-Spezifikation definiert u1, u2, u4 und u8 zur Darstellung vorzeichenloser Zahlen von 1 Byte, 2 Byte, 4 Byte und 8 Byte. Zur Beschreibung von Zahlen und Indizes können Referenzen, Mengen oder Zeichenfolgen verwendet werden. Eine Tabelle ist ein zusammengesetzter Datentyp, der aus mehreren vorzeichenlosen Zahlen oder anderen Tabellen als Datenelementen besteht. Die Tabelle wird verwendet, um Daten mit einer hierarchischen zusammengesetzten Struktur zu beschreiben, sodass die gesamte Klassendatei im Wesentlichen eine Tabelle ist. In ClassAnalyzer entsprechen Byte, Short, Int und Long den Datentypen u1, u2, u4 und u8. Die Klassendatei wird als die folgende Java-Klasse beschrieben.
public class ClassFile { public U4 magic; // magic public U2 minorVersion; // minor_version public U2 majorVersion; // major_version public U2 constantPoolCount; // constant_pool_count public ConstantPoolInfo[] cpInfo; // cp_info public U2 accessFlags; // access_flags public U2 thisClass; // this_class public U2 superClass; // super_class public U2 interfacesCount; // interfaces_count public U2[] interfaces; // interfaces public U2 fieldsCount; // fields_count public FieldInfo[] fields; // fields public U2 methodsCount; // methods_count public MethodInfo[] methods; // methods public U2 attributesCount; // attributes_count public BasicAttributeInfo[] attributes; // attributes }
So analysieren Sie die verschiedenen Datenelemente, aus denen die Klassendatei besteht, z. B. magische Zahlen und Klassendateiversionen sowie andere Datenelemente und Zugriffsflags , Klassenindex, übergeordneter Klassenindex, sie belegen eine feste Anzahl von Bytes in jeder Klassendatei, und beim Parsen muss nur die entsprechende Anzahl von Bytes gelesen werden. Darüber hinaus müssen hauptsächlich vier Teile flexibel gehandhabt werden: Konstantenpool, Feldtabellensammlung, Methodentabellensammlung und Attributtabellensammlung. Felder und Methoden können ihre eigenen Attribute haben, und die Klasse selbst verfügt auch über entsprechende Attribute. Daher umfasst das Parsen der Feldtabellensammlung und Methodentabellensammlung auch das Parsen der Attributtabelle.
Class的文件方法表采用了和字段表相同的存储格式,只是access_flags对应的含义有所不同。方法表包含着一个重要的属性:Code属性。Code属性存储了Java代码编译成的字节码指令,在ClassAnalyzer中,Code对应的Java类如下所示(仅列出了类属性)
public class Code extends BasicAttributeInfo { private short maxStack; private short maxLocals; private long codeLength; private byte[] code; private short exceptionTableLength; private ExceptionInfo[] exceptionTable; private short attributesCount; private BasicAttributeInfo[] attributes; ... private class ExceptionInfo { public short startPc; public short endPc; public short handlerPc; public short catchType; ... } }
在Code属性中,codeLength和code分别用于存储字节码长度和字节码指令,每条指令即一个字节(u1类型)。在虚拟机执行时,通过读取code中的一个个字节码,并将字节码翻译成相应的指令。另外,虽然codeLength是一个u4类型的值,但是实际上一个方法不允许超过65535条字节码指令。
代码实现
ClassAnalyzer的源码已放在了GitHub上。在ClassAnalyzer的README中,我以一个类的Class文件为例,对该Class文件的每个字节进行了分析,希望对大家的理解有所帮助。
Das obige ist der detaillierte Inhalt vonBeispiel einer Methode zum Implementieren eines Klassenparsers in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!