您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“為什么給Java代碼加個空行class文件就不響應了”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“為什么給Java代碼加個空行class文件就不響應了”吧!
1. 翻臉不認人
Java號稱一次編譯到處運行,大概就是class文件的功勞。不同的Java版本編譯之后的class文件那是肯定不一樣的,因為里面有一個版本號,那肯定影響了它們的內(nèi)容。
我們就看一下,如果給上面的代碼,加一個空行,它的class文件會不會變。
這個空行還不能隨便加。它可能在xjjdog上面,也可能在下面??赡茉趝中,也可能在文件末尾。
(1) 打臉
在驗證之前,我們先看一下當前的class文件md5值。
我非常喜歡被打臉,所以先看一種加空行也無所謂的情況。
再次編譯之后看md5值,果然被打臉了。還好我已經(jīng)練就了臉不紅心不跳的本領,這個結果厚著臉皮接受。
(2) 抹藥
為了和主題遙相呼應,安慰一下受傷的心靈,我們把空行轉(zhuǎn)移到了這里。
再次編譯之后,看md5值(怎么感覺這句話已經(jīng)說過了呢)。
變了。這次真的變了。
使用hexdump命令分析兩次生成的字節(jié)碼,發(fā)現(xiàn)其中只不過變了一個數(shù)字。
2. 騷戴斯乃
特別不喜歡分析這種二進制的東西。雖然CAFEBABE這個魔數(shù)在第一行歷歷在目??Х葘氊?怎么聽著像是某個番號?
我們還是用javap來看一下它的原型。
javap -p -v HelloWorld.class
通過對比兩次生成的字節(jié)碼,我們終于發(fā)現(xiàn)了這個變動,是一個叫做LineNumberTable的結構引起的。
使用asmtools.jar深入分析這個結構,可以看到同樣的信息。
LineNumberTable展示了Java源碼行號和字節(jié)碼指令的對應關系。前面的數(shù)字代表Java源代碼中的行號,而冒號后面的則代表字節(jié)碼里每行指令的映射關系。在對代碼進行調(diào)試的時候,能夠快速定位,順利進行。
也就是說,這些是輔助信息,我們可以在編譯的時候抹掉它。怎么抹掉呢?給javac一個參數(shù)就ok了。
javac -g:none HelloWorld.java
這樣編譯后的字節(jié)碼,緊湊、優(yōu)雅、無用。不管你加多少空行,生成的字節(jié)碼都是一樣的??墒?,我們再也不能暢快淋漓的進行調(diào)試了。
{ 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."<init>":()V 4: return public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Hello xjjdog 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
要想在開發(fā)階段讓字節(jié)碼又香又有用,可以直接使用參數(shù)-g開啟所有調(diào)試信息。IDEA可以在編譯選項里對這個參數(shù)進行開啟。有很多同學在編譯之后的代碼里找不到局部變量的符號表,也是由于這個參數(shù)沒有開啟所引起的。
到此,相信大家對“為什么給Java代碼加個空行class文件就不響應了”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。