dex2jar在dex和jar轉換時加入 -d 參數的異常處理

最近在做一個android項目,由於項目需要。在對生成的源apk文件做單獨的處理。大致流程爲解壓apk,生成dex文件,將dex文件轉爲jar。修改jar後,再將jar轉爲dex文件。

將dex轉爲jar需要使用命令:java -Xms512m -Xmx1024m -classpath dex2jar.jar com.googlecode.dex2jar.tools.Dex2jarCmd -o classes.jar classes.dex

但是該命令關閉了debug模式,用JclassLib查看生成的classes.jar文件,發現沒有LocalVariableTable和LineNumberTable兩個屬性值。

LocalVariableTable是本地變量表,對於我這個項目而言,沒有實際意義。但是LineNumberTable沒有的話,導致的結果是如果有異常拋出,無法查看行數。

於是,我使用了java -Xms512m -Xmx1024m -classpath dex2jar.jar com.googlecode.dex2jar.tools.Dex2jarCmd  -d -o classes.jar classes.dex,加入了-d的參數。

生成了新的jar包文件,查看有本地變量屬性和行數。

但是,再次將jar包轉爲dex時,命令:java -Xms512m -Xmx1024m -classpath dex2jar.jar com.googlecode.dex2jar.tools.Jar2Dex -o /classes.dex classes.jar。

由於dex2jar需要先走讀一次代碼,發現在某個接口時直接拋出異常:local variable type mismatch: attempt to set or access a value of type java.lang.Object using a local variable of type int. This is symptomatic of .class transformation tools that ignore local variable information. int型和object類型不匹配。

這個問題,我查找了很長的時間。對於同樣地出問題的接口,裏面有一句 byte[] test = new byte[1024]。修改位byte[] test = null。就可以編譯通過。

另外,保持如上改動不邊,移除掉異常捕獲的代碼(採用throw的方式),也可以讓在jar轉爲dex的時候,通過。

由於類似的異常問題,在其他接口中也存在,因此只能從dex2jar的源碼下手,計劃移除掉LocalVariableTable屬相。

在使用JclassLib對比了生成的jar和原生jar(使用eclipse直接讓項目生成jar),對比出問題的接口,發現dexJar和原生Jar差別很大。可能由於編碼指令不同,dexJar的code使用了非常多的goto跳轉。逐行分析了dexJar的code,發現該code和LocalVariableTable不匹配,code中定義的某個int型變量,在LocalVariableTable中查看週期發現爲Object類型。

因此我分析原因爲,由於dexJar的code和LocalVariableTable不匹配,導致後面在將jar轉爲dex的時候,走讀代碼時,需要校驗兩者,無法通過,因此才拋出了上述問題。

通過查看dex2jar的源碼,發現LocalVariableTable和LineNumberTable是同時收到-d參數控制(這兩個屬相在同一個java文件中實現),感興趣的可以去看看

com.googlecode.dex2jar.reader.DexDebugInfoReader.java ,只要註釋掉visitLocalVariable接口的調用,其他地方不用修改,這樣就可以關閉LocalVariableTable,而同時LineNumberTable正常。

已經在我的項目中驗證過。有需要的可以試試我這個方法,記的加上 -d 參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章