Tekintse meg az osztályfájl Bytecode-ját a Java-ban
1. Áttekintés
A bytecode elemzés sok okból elterjedt gyakorlat a Java-fejlesztők körében, például a kóddal kapcsolatos problémák keresése, a kódprofilozás és az osztályok keresése speciális kommentárokkal.
Ebben a cikkben azt vizsgáljuk, hogy miként tekinthető meg az osztályfájl bájtkódja Java-ban.
2. Mi a Bytecode?
A Bytecode a Java program közbenső ábrázolása, amely lehetővé teszi a JVM számára, hogy a programot gépi szintű összeszerelési utasításokká fordítsa.
Amikor Java programot fordítanak, a bytecode generálódik a formájában .osztály fájl. Ez .osztály fájl nem futtatható utasításokat tartalmaz, és egy értelmezendő JVM-re támaszkodik.
3. Használata javap
A Java parancssor a javap eszköz, amely információkat jelenít meg egy osztályfájl mezőiről, szerkesztőiről és módszereiről.
A felhasznált opciók alapján szétszerelhet egy osztályt, és megjelenítheti a Java byte-kódot tartalmazó utasításokat.
3.1. javap
Használjuk a javap parancs a leggyakoribb bájtkódjának megtekintéséhez Tárgy osztály:
$ javap java.lang.Object
A parancs kimenete megmutatja a Tárgy osztály:
java.lang.Object {public java.lang.Object () osztály; nyilvános végleges natív java.lang.Class getClass (); public native int hashCode (); nyilvános logikai egyenlő (java.lang.Object); védett natív java.lang.Object clone () dobja java.lang.CloneNotSupportedException; nyilvános java.lang.String toString (); nyilvános végleges natív érvénytelen értesítés (); nyilvános végleges natív érvénytelen értesítésAll (); public final native void wait (long) dobja a java.lang.InterruptedException; public final void wait (long, int) dobja a java.lang.InterruptedException; public final void wait () dobja a java.lang.InterruptedException; protected void finalize () dobja a java.lang.Trowble-t; statikus {}; }
Alapértelmezés szerint a bytecode kimenet nem tartalmaz mezőket / metódusokat a egy közlegény hozzáférés módosító.
3.2. javap-p
Az összes osztály és tag megtekintéséhez használhatjuk a -p érv:
java.lang.Object {public java.lang.Object () osztály; privát statikus natív űrregiszterNatívok (); nyilvános végleges natív java.lang.Class getClass (); public native int hashCode (); nyilvános logikai egyenlő (java.lang.Object); védett natív java.lang.Object clone () dobja java.lang.CloneNotSupportedException; // ...}
Itt megfigyelhetjük a magán módszer registerNatives a bájtkódjában is látható Tárgy osztály.
3.3. javap-v
Hasonlóképpen használhatjuk a -v argumentum a részletes információk, például a verem méretének és a Tárgy osztály:
Osztályfájl jar: fájl: /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar! /Java/lang/Object.class Utolsó módosítás: 2017. március 15 .; 1497 byte MD5 ellenőrző összeg 5916745820b5eb3e5647da3b6cc6ef65 Összeállítva az "Object.java" nyilvános osztály java.lang.Object minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: # 1 = Class # 49 // java / lang / StringB / ... {public java.lang.Object (); leíró: () V zászlók: ACC_PUBLIC Kód: verem = 0, helyiek = 1, args_size = 1 0: return LineNumberTable: 37. sor: 0 nyilvános végleges natív java.lang.Class getClass (); leíró: () Ljava / lang / Class; zászlók: ACC_PUBLIC, ACC_FINAL, ACC_NATIVE Aláírás: # 26 // () Ljava / lang / Class; // ...} SourceFile: "Object.java"
3.4. javap-c
Továbbá a javap parancs lehetővé teszi a teljes Java osztály szétszerelését a -c érv:
Összeállítva az "Object.java" nyilvános osztályból java.lang.Object {public java.lang.Object (); Kód: 0: return public boolean egyenlő (java.lang.Object); Kód: 0: aload_0 1: aload_1 2: if_acmpne 9 5: iconst_1 6: goto 10 9: iconst_0 10: védett natív java.lang.Object klón () dobja a java.lang.CloneNotSupportedException; // ...}
Továbbá a javap parancs lehetővé teszi számunkra, hogy különféle argumentumok segítségével ellenőrizzük a rendszerinformációkat, az állandókat és a belső típusú aláírásokat.
Felsorolhatunk minden argumentumot, amelyet a javap parancsot a -Segítség érv.
Most, hogy láttunk egy Java parancssori megoldást egy osztályfájl bájtkódjának megtekintésére, vizsgáljunk meg néhány bájtkód-manipulációs könyvtárat.
4. Az ASM használata
Az ASM egy népszerű teljesítményorientált, alacsony szintű Java bytecode manipulációs és elemzési keretrendszer.
4.1. Beállít
Először tegyük hozzá a legfrissebbet asm és asm-util Maven függőségek a mi pom.xml:
org.ow2.asm asm 8.0.1 org.ow2.asm asm-util 8.0.1
4.2. A Bytecode megtekintése
Akkor használjuk a ClassReader és TraceClassVisitor hogy megtekinthesse a Tárgy osztály:
próbáld ki a {ClassReader olvasót = új ClassReader ("java.lang.Object"); StringWriter sw = új StringWriter (); TraceClassVisitor tcv = új TraceClassVisitor (új PrintWriter (System.out)); olvasó.elfogad (tcv, 0); } catch (IOException e) {e.printStackTrace (); }
Itt megjegyezzük, hogy a TraceClassVisitor objektum megköveteli a PrintWriter objektum a bájtkód kinyerésére és előállítására:
// class version 52.0 (52) // access flags 0x21 public class java / lang / Object {// fordítva: Object.java // hozzáférési flagek 0x1 public () V L0 LINENUMBER 37 L0 RETURN MAXSTACK = 0 MAXLOCALS = 1 / / access flags 0x101 public native hashCode () I // access flags 0x1 public egyenlő (Ljava / lang / Object;) Z L0 LINENUMBER 149 L0 ALOAD 0 ALOAD 1 IF_ACMPNE L1 ICONST_1 GOTO L2 L1 // ...}
5. A BCEL használata
A Byte Code Engineering Library, közismertebb nevén Apache Commons BCEL, kényelmes módot kínál a Java osztályú fájlok létrehozására / kezelésére.
5.1. Maven-függőség
Szokás szerint tegyük hozzá a legfrissebbet bcel Maven függőség a mi pom.xml:
org.apache.bcel bcel 6.5.0
5.2. Szedje szét az osztályt és nézze meg a Bytecode-ot
Ezután használhatjuk a Adattár osztály a JavaClass tárgy:
próbáld ki a {JavaClass objectClazz = Repository.lookupClass ("java.lang.Object") parancsot; System.out.println (objectClazz.toString ()); } catch (ClassNotFoundException e) {e.printStackTrace (); }
Itt használtuk a Sztring módszer a objectClazz objektum, hogy tömör formátumban lássa a bájtkódot: Továbbá a JavaClass osztály olyan módszereket nyújt, mint getConstantPool, getFields, és getMethods a szétszedett osztály részleteinek megtekintéséhez. Hasonlóképpen, készlet* módszerek állnak rendelkezésre a bytecode manipulációra. Használhatjuk a Javassist (Java programozási asszisztens) könyvtár, amely magas szintű API-kat biztosít a Java bytecode megtekintésére / kezelésére. Először hozzáadjuk a legfrissebbet javassist Maven függőség a mi pom.xml: Ezután használhatjuk a ClassPool és ClassFile osztályok Java osztály létrehozásához: Itt használtuk a ír metódus, amely lehetővé teszi számunkra, hogy az osztályfájlt a DataOutputStream tárgy: Továbbá a ClassFile osztály hozzáférést biztosít az állandó készlethez, mezőkhöz és módszerekhez: Ezenkívül egy IDE alapú beépülő modult is használhatunk egy osztályfájl byte-kódjának megtekintésére. Fedezzük fel például a jclasslib Bytecode néző bővítmény elérhető az IntelliJ IDEA számára. Először telepítjük a beépülő modult a Beállítások / Beállítások párbeszédpanelen: Ezután kiválaszthatjuk a Nézet menü „Bitecode megjelenítése Jclasslib-lel” opciót a kiválasztott bájtkódjának megtekintéséhez. Tárgy osztály: Ezután megnyílik egy párbeszédpanel, amely megmutatja a Tárgy osztály: Ezenkívül a Jclasslib plugin párbeszédpanel segítségével láthatjuk a bájtkód különböző részleteit, például az állandó készletet, a mezőket és a módszereket: Hasonlóképpen megvan a Bytecode Visualizer beépülő modul osztályfájl bájtkódjának megtekintéséhez az Eclipse IDE használatával. Ebben az oktatóanyagban megvizsgáltuk, hogyan lehet egy osztályfájlt bájtkódot megtekinteni Java-ban. Először megvizsgáltuk a javap parancsot a különböző érveivel együtt. Ezután átmentünk néhány bytecode manipulációs könyvtáron, amelyek biztosítják a bytecode megtekintésének és kezelésének lehetőségeit. Utoljára egy IDE alapú plugint vizsgáltunk Jclasslib ez lehetővé teszi számunkra a bytecode megtekintését az IntelliJ IDEA-ban. Szokás szerint az összes kód implementáció elérhető a GitHubon.java.lang.objekt fájlnév java.lang.Object az Object.java fordító 52.0-s verziójából összeállítva hozzáférési jelzők 33 állandó készlet 78 bejegyzés ACC_SUPER flag true Attribútum (ok): SourceFile: Object.java 14 módszer: public void () private static native void registerNatives () public final native class getClass () [Signature: () Ljava / lang / Class;] public native int hashCode () public boolean egyenlő (Object arg1) védett natív Object klón () dobja a kivételeket: java.lang .CloneNotSupportedException public String toString () nyilvános végleges natív érvénytelen értesítés () // ...
assertEquals (objectClazz.getFileName (), "java.lang.Object"); assertEquals (objectClazz.getMethods (). hossz, 14); assertTrue (objectClazz.toString (). tartalmazza ("java.lang.Object nyilvános osztály"));
6. Javassist használata
6.1. Maven-függőség
org.javassist javassist 3.27.0-GA
6.2. generál ClassFile
próbáld ki a {ClassPool cp = ClassPool.getDefault (); ClassFile cf = cp.get ("java.lang.Object"). GetClassFile (); cf.write (új DataOutputStream (új FileOutputStream ("Object.class"))); } catch (NotFoundException e) {e.printStackTrace (); }
// Az Object.java (1.8 verzió: 52.0, szuper bit) Public class java.lang.Object {// Metódusleíró # 19 () V // Verem: 0, Helyiek: 1 nyilvános objektum (); 0 return Sorszámok: [pc: 0, sor: 37] // Metódleíró # 19 () V privát statikus natív void registerNatives (); // Metódleíró # 24 () Ljava / lang / Class; // Aláírás: () Ljava / lang / Class; nyilvános végleges natív java.lang.Class getClass (); // Módszerleíró # 28 () I public native int hashCode (); // ...
assertEquals (cf.getName (), "java.lang.Object"); assertEquals (vö .getMethods (). méret (), 14);
7. Jclasslib
7.1. Telepítés
7.2. Tekintse meg a Tárgy Osztály
7.3. Részletek megtekintése
8. Következtetés