Cet article présente principalement des exemples de méthodes d'implémentation de l'analyseur de classe Java via l'analyse des fichiers de classe. Il a une certaine valeur de référence et les amis dans le besoin peuvent en apprendre davantage.
Récemment, j'écris un projet privé appelé ClassAnalyzer. Le but de ClassAnalyzer est de nous donner une compréhension approfondie de la conception et de la structure des fichiers de classe Java. Le cadre principal et les fonctions de base ont été complétés, et certaines fonctions détaillées seront ajoutées à l'avenir. En fait, JDK fournit déjà l'outil de ligne de commande javap pour décompiler les fichiers de classe, mais cet article clarifiera mon idée d'implémenter l'analyseur.
Fichier de classe
En tant que support d'informations de classe ou d'interface, chaque fichier de classe définit complètement une classe. Afin de permettre aux programmes Java d'être « écrits une seule fois et exécutés n'importe où », la spécification de la machine virtuelle Java impose des réglementations strictes sur les fichiers de classe. L'unité de données de base qui constitue un fichier de classe est l'octet. Il n'y a pas de séparateur entre ces octets, ce qui fait que le contenu stocké dans l'intégralité du fichier de classe est représenté par. multiple Représenté par des octets consécutifs.
Selon la spécification de la machine virtuelle Java, le fichier Class utilise une pseudo-structure similaire à la structure du langage C pour stocker les données. Il n'y a que deux types de données dans cette pseudo-structure : les nombres non signés et. tableaux. La spécification de la machine virtuelle Java définit u1, u2, u4 et u8 pour représenter des nombres non signés de 1 octet, 2 octets, 4 octets et 8 octets respectivement. Les nombres non signés peuvent être utilisés pour décrire des nombres et des index. Une référence, une quantité ou une chaîne. Une table est un type de données composite composé de plusieurs nombres non signés ou d'autres tables comme éléments de données. La table est utilisée pour décrire des données avec une structure composite hiérarchique, de sorte que l'ensemble du fichier de classe est essentiellement une table. Dans ClassAnalyzer, byte, short, int et long correspondent respectivement aux types de données u1, u2, u4 et u8. Le fichier Class est décrit comme la classe Java suivante.
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 }
Comment analyser les différents éléments de données qui composent le fichier de classe, tels que les nombres magiques et les fichiers de classe. Version et autres éléments de données, indicateurs d'accès , index de classe, index de classe parent, ils occupent un nombre fixe d'octets dans chaque fichier de classe, et seul le nombre d'octets correspondant doit être lu lors de l'analyse. De plus, il y a principalement quatre parties qui doivent être gérées de manière flexible : le pool de constantes, la collection de tables de champs, la collection de tables de méthodes et la collection de tables attributaires. Les champs et les méthodes peuvent avoir leurs propres attributs, et la classe elle-même a également les attributs correspondants. Par conséquent, l'analyse de la collection de tables de champs et de la collection de tables de méthodes inclut également l'analyse de la table attributaire.
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文件的每个字节进行了分析,希望对大家的理解有所帮助。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!