Maison  >  Article  >  Java  >  Exemple de méthode pour implémenter l'analyseur de classe en Java

Exemple de méthode pour implémenter l'analyseur de classe en Java

黄舟
黄舟original
2017-09-15 10:16:001293parcourir

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.

Le pool de constantes occupe une grande partie des données du fichier de classe et est utilisé pour stocker toutes les informations de constantes, y compris les constantes numériques et de chaîne, les noms de classe, les noms d'interface, les noms de champs, les noms de méthodes, etc. La spécification de la machine virtuelle Java définit plusieurs types de constantes, chacun possédant sa propre structure. Le pool constant lui-même est une table, et il y a plusieurs points à noter lors de son analyse.


Chaque type de constante est identifié par une balise de type u1.


La taille du pool constant (constantPoolCount) indiquée dans l'en-tête est 1 supérieure à la valeur réelle. Par exemple, si constantPoolCount est égal à 47, alors il y a 46 constantes dans le pool constant.


La plage d'index du pool constant commence à partir de 1. Par exemple, si constantPoolCount est égal à 47, alors la plage d'index du pool constant est de 1 à 46. Le but du concepteur de laisser l'élément 0 vide est d'exprimer "ne faisant référence à aucun élément de pool constant".


La structure de la constante CONSTANT_Utf8_info contient une balise de type u1, une longueur de type u2 et une longueur d'octets de type u1. Les données continues de longueur octets sont des données continues utilisant MUTF-8 (Modifié. Chaîne codée en UTF-8). MUTF-8 n'est pas compatible avec UTF-8. Il existe deux différences principales : premièrement, le caractère nul sera codé sur 2 octets (0xC0 et 0x80). Deuxièmement, les caractères supplémentaires sont divisés en paires de substitution et codés séparément selon UTF ; -16 , les détails pertinents peuvent être trouvés ici (variante UTF-8).


Les tables attributaires sont utilisées pour décrire des informations spécifiques à certains scénarios. Les fichiers de classe, les tables de champs et les tables de méthodes ont tous des ensembles de tables attributaires correspondants. La spécification de la machine virtuelle Java définit une variété d'attributs et ClassAnalyzer implémente actuellement l'analyse des attributs couramment utilisés. Contrairement aux éléments de données de type constant, les attributs n'ont pas de balise pour identifier le type de l'attribut, mais chaque attribut contient un attribut_name_index de type u2. Attribute_name_index pointe vers une constante de type CONSTANT_Utf8_info dans le pool de constantes, qui contient le nom de l'attribut. Lors de l'analyse des attributs, ClassAnalyzer connaît le type de l'attribut via le nom d'attribut correspondant à la constante pointée parattribut_name_index.


La table de champs est utilisée pour décrire les variables déclarées dans une classe ou une interface. Les champs incluent des variables au niveau de la classe et des variables au niveau de l'instance. La structure de la table de champs comprend un access_flags de type u2, un name_index de type u2, un descriptor_index de type u2, un attributs_count de type u2 et des attributs de type attribues_count attribues_info. Nous avons déjà introduit l'analyse des tables attributaires. La méthode d'analyse des attributs est cohérente avec la méthode d'analyse des tables attributaires.


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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn