為了寫出這幾行優美的代碼,主要是為了讓它輸出優美動聽的樂符,我下了一番功夫。你不要覺得簡單,我把它打印出來給普通的保潔阿姨去看,阿姨竟然連xjjdog都認不出來。別說代碼了,中英文混血,就秒殺一大堆高干分子。
想說愛我就那么難么?怎么這么多的廢話呢?這次探討的主要問題是,給Java源文件加個空行之后,它生成的字節碼,會有變化么?
1、翻臉不認人
Java號稱一次編譯到處運行,大概就是class文件的功勞。不同的Java版本編譯之后的class文件那是肯定不一樣的,因為里面有一個版本號,那肯定影響了它們的內容。
我們就看一下,如果給上面的代碼,加一個空行,它的class文件會不會變。
這個空行還不能隨便加。它可能在xjjdog上面,也可能在下面??赡茉趝中,也可能在文件末尾。
1.1、打臉
在驗證之前,我們先看一下當前的class文件md5值。
我非常喜歡被打臉,所以先看一種加空行也無所謂的情況。
再次編譯之后看md5值,果然被打臉了。還好我已經練就了臉不紅心不跳的本領,這個結果厚著臉皮接受。
1.2、抹藥
為了和主題遙相呼應,安慰一下受傷的心靈,我們把空行轉移到了這里。
再次編譯之后,看md5值(怎么感覺這句話已經說過了呢)。
變了。這次真的變了。
使用hexdump命令分析兩次生成的字節碼,發現其中只不過變了一個數字。
2、騷戴斯乃
特別不喜歡分析這種二進制的東西。雖然CAFEBABE這個魔數在第一行歷歷在目??Х葘氊??怎么聽著像是某個番號?
我們還是用javap來看一下它的原型。
javap -p -v HelloWorld.class
通過對比兩次生成的字節碼,我們終于發現了這個變動,是一個叫做LineNumberTable的結構引起的。
使用asmtools.jar深入分析這個結構,可以看到同樣的信息。
LineNumberTable展示了Java源碼行號和字節碼指令的對應關系。前面的數字代表Java源代碼中的行號,而冒號后面的則代表字節碼里每行指令的映射關系。在對代碼進行調試的時候,能夠快速定位,順利進行。
也就是說,這些是輔助信息,我們可以在編譯的時候抹掉它。怎么抹掉呢?給javac一個參數就ok了。
javac -g:none HelloWorld.java
這樣編譯后的字節碼,緊湊、優雅、無用。不管你加多少空行,生成的字節碼都是一樣的??墒牵覀冊僖膊荒軙晨炝芾斓倪M行調試了。
{ public HelloWorld(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."
要想在開發階段讓字節碼又香又有用,可以直接使用參數-g開啟所有調試信息。IDEA可以在編譯選項里對這個參數進行開啟。有很多同學在編譯之后的代碼里找不到局部變量的符號表,也是由于這個參數沒有開啟所引起的。
END
麻雀雖小,五臟俱全。能寫HelloWorld,就證明已經凌駕于大部分人之上,能了解這些東西,就證明已經是人上之人。怪不得大家都說:就差一個程序員了。
HelloWorld,表面上看起來人五人六,原來背地里都有自己的小99啊。
-
JAVA
+關注
關注
20文章
2983瀏覽量
106489 -
代碼
+關注
關注
30文章
4880瀏覽量
69987 -
Class
+關注
關注
0文章
53瀏覽量
19972
發布評論請先 登錄
相關推薦
評論