javap的用途不断发展:您的Java类文件中隐藏了什么?
什么是Javap,如何使用它以及何時要反匯編類文件?
作為Java開發(fā)工具包(JDK)的一部分,我們可以使用許多工具,這些工具有助于更好地理解Java代碼。 這些工具之一是javap命令,它為我們提供了對Java類文件的后臺傳遞。
在下面的文章中,我們將研究javap,了解它如何為我們提供幫助,并確切地了解如何使用它。 代碼,反匯編!
什么是javap?
javap是一個命令行工具,可分解Java類文件:它分解了我們的類文件,并揭示了其中的內(nèi)容。 該工具將二進制格式的類文件轉(zhuǎn)換為人類可讀的代碼。 好吧,對于某些人。
javap提供了許多輸出,這些輸出根據(jù)我們感興趣的數(shù)據(jù)而有所不同。默認情況下,javap打印每個類的非私有成員的聲明。
至于javap中的p代表什么,所有證據(jù)都指向“打印”,因為javap命令會打印出類中的字節(jié)碼。
我們可以使用javap的一種好方法是探索異常。 如果您想提高自己的知識并了解引發(fā)異常時會發(fā)生什么,請查看我們的文章,了解有關(guān)Java異常的令人驚訝的真相 。
在我們的類中使用javap
既然我們知道了javap是什么,該是在我們的代碼上嘗試使用它的時候了。 我們通過鍵入命令,選擇一個選項并添加類名來做到這一點:
javap [選項]類名
正如我們指出的,這些選項(也可以稱為標志)將決定我們的輸出是什么。 我們可以從許多標志中進行選擇,包括:
- -l –輸出行和局部變量表
- -public –僅顯示公共班級和成員
- -protected –僅顯示受保護的和公開的班級和成員
- -package –僅顯示軟件包,受保護的和公共的類和成員
- -p –顯示所有班級和成員
- -Jflag –將標志直接傳遞到運行時系統(tǒng)
- -s –打印內(nèi)部類型簽名
- -sysinfo –顯示正在處理的類的系統(tǒng)信息(路徑,大小,日期,MD5哈希)
- -constants –顯示靜態(tài)最終常量
- -c –打印反匯編的代碼
- -verbose –打印堆棧大小,方法的局部變量和args
用javap深入字節(jié)碼
在列出了可以使用javap進行的操作之后,現(xiàn)在該弄清楚它的實際工作方式了。 為此,我們創(chuàng)建了一個名為ExampleClass的基本類:
public class ExampleClass {private int a = 0;private int b = 0;public static void main(String[] args) {System.out.println("Hello world!");} }現(xiàn)在讓我們在javap的幫助下更深入地研究它。 首先,我們將使用不帶任何其他標志的javap命令來打印出非私有成員。 我們的輸出是這樣的:
$ javap ExampleClassCompiled from "ExampleClass.java" public class ExampleClass {public ExampleClass();public static void main(java.lang.String[]); }如您所見,這是原始代碼的漂亮“普通”視圖,沒有有關(guān)私有整數(shù)和邏輯的任何信息。 這是一個好的開始,但是如果我們想更深入地了解呢? 讓我們嘗試使用-c打印出反匯編的代碼:
$ javap -c ExampleClassCompiled from "ExampleClass.java" public class ExampleClass {public ExampleClass();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: iconst_06: putfield #2 // Field a:I9: aload_010: iconst_011: putfield #3 // Field b:I14: returnpublic static void main(java.lang.String[]);Code:0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #5 // String Hello world!5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return }現(xiàn)在,我們的字節(jié)碼具有某種可讀性,可以在其中識別我們的方法,整數(shù),命令和字符串。 但是等等,還有更多。 如果我們想了解有關(guān)該課程的更多信息怎么辦? 那是我們?nèi)唛L的標志可以幫助我們的地方:
$ javap -v ExampleClassClassfile /Users/es/ExampleClass.classLast modified May 22, 2017; size 496 bytesMD5 checksum 7d29362228a3128e67b0c20c8bb54ee1Compiled from "ExampleClass.java" public class ExampleClassSourceFile: "ExampleClass.java"minor version: 0major version: 51flags: ACC_PUBLIC, ACC_SUPER Constant pool:#1 = Methodref #8.#20 // java/lang/Object."<init>":()V#2 = Fieldref #7.#21 // ExampleClass.a:I#3 = Fieldref #7.#22 // ExampleClass.b:I#4 = Fieldref #23.#24 // java/lang/System.out:Ljava/io/PrintStream;#5 = String #25 // Hello world!#6 = Methodref #26.#27 // java/io/PrintStream.println:(Ljava/lang/String;)V#7 = Class #28 // ExampleClass#8 = Class #29 // java/lang/Object#9 = Utf8 a#10 = Utf8 I#11 = Utf8 b#12 = Utf8 <init>#13 = Utf8 ()V#14 = Utf8 Code#15 = Utf8 LineNumberTable#16 = Utf8 main#17 = Utf8 ([Ljava/lang/String;)V#18 = Utf8 SourceFile#19 = Utf8 ExampleClass.java#20 = NameAndType #12:#13 // "<init>":()V#21 = NameAndType #9:#10 // a:I#22 = NameAndType #11:#10 // b:I#23 = Class #30 // java/lang/System#24 = NameAndType #31:#32 // out:Ljava/io/PrintStream;#25 = Utf8 Hello world!#26 = Class #33 // java/io/PrintStream#27 = NameAndType #34:#35 // println:(Ljava/lang/String;)V#28 = Utf8 ExampleClass#29 = Utf8 java/lang/Object#30 = Utf8 java/lang/System#31 = Utf8 out#32 = Utf8 Ljava/io/PrintStream;#33 = Utf8 java/io/PrintStream#34 = Utf8 println#35 = Utf8 (Ljava/lang/String;)V {public ExampleClass();flags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: iconst_06: putfield #2 // Field a:I9: aload_010: iconst_011: putfield #3 // Field b:I14: returnLineNumberTable:line 1: 0line 3: 4line 4: 9public static void main(java.lang.String[]);flags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #5 // String Hello world!5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 7: 0line 8: 8 }很多行在我們面前展開。 我們可以看到以下內(nèi)容:
1.元數(shù)據(jù)–此類文件的位置,上次修改時間以及具有其唯一ID的類哈希
2.常量池–結(jié)構(gòu)表,它引用ClassFile結(jié)構(gòu)及其子結(jié)構(gòu)中的各種常量。 它保存類,接口,類實例,字段名稱,字符串常量或數(shù)組的符號信息。
3.字節(jié)碼–用JVM可以“讀取”的語言編寫的指令集
在OverOps,我們使用javap作為研究工具來挖掘類。 我們最近使用它來發(fā)現(xiàn)IBM J9的工作原理,為使用此JVM的開發(fā)人員提供支持。 如果您想了解更多有關(guān)我們?nèi)绾螏椭鷪F隊減少調(diào)試時間并知道代碼在何時何地中斷的原因, 請單擊此處以安排演示 。
現(xiàn)在我們知道了如何使用javap,是時候回答一個重要的問題了:
到底有什么好處呢?
Javap很酷,特別是如果您是像我們這樣的數(shù)據(jù)迷并且想知道代碼背后發(fā)生了什么時。 但是除了不錯的代碼探索冒險外,它也非常有用。
對于原始源代碼不可用的情況,它可能會派上用場,其中顯示了可以使用的方法。 它還可以幫助找出別人的代碼或3rd party類中的內(nèi)容。
我們還可以將javap用作Java類的類驗證器,以確保每個加載的類文件都以適當?shù)姆绞竭M行結(jié)構(gòu)化。
剛開始,javap感覺就像是一根魔杖,可以在代碼內(nèi)為我們提供所有信息,但它并不是對我們所面臨的每個問題的完整解決方案。 它可能會幫助“逆向工程”某些代碼,但這只是一個復雜難題中的一個線索。
如果您正在尋找一種將javap字節(jié)碼輸出轉(zhuǎn)換為功能性Java代碼的方法,而不僅僅是“數(shù)據(jù)列表”,那么您將需要反編譯工具(如JD , Mocha等)的幫助。
最后的想法
盡管您不會經(jīng)常使用它,但是javap是一個有用的工具,請牢記。 除了這是一個很酷的“技巧”之外,它還更深入地介紹了Java代碼,向我們展示了幕后發(fā)生的事情以及JVM如何使用我們的代碼。
翻譯自: https://www.javacodegeeks.com/2017/06/javap-usage-unfolds-whats-hidden-inside-java-class-files.html
總結(jié)
以上是生活随笔為你收集整理的javap的用途不断发展:您的Java类文件中隐藏了什么?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梅字怎么组词 梅拼音及释义
- 下一篇: Unity 收取“运行费”引众怒,《杀戮