天天看點

dex2jar 和 jd-gui

dex2jar反編譯的時候出了點問題:

輸出錯誤

Detail Error Information in File ./APK-error.zip

看了下大多數都是一樣的問題:

java.lang.RuntimeException: can not merge I and Z

sourceforge上解釋就是錯誤的原因在于一個參數異常,其實就是寫代碼的人故意把booleanl和int類型混淆,導緻dex2jar出錯

解決方案:

1、如果出錯代碼量不大的話可以直接修改代碼,也即修改 smali 檔案,在出錯的地方加一個對類型的判斷和指派,參見https://github.com/pxb1988/dex2jar/issues/11;

2、如果需要修改的代碼量太多,或者想一勞永逸解決這個問題,也可以去修改dex2jar,針對bug出現的函數做類型修複。

BTW,這個 bug 是2015/5/13被提出來,作者第二天就做了回複,後續版本的 dex2jar 已經修複了這個問題。目前市面上的流通的dex2jar_2.0,dex2jar_2.1 都是老版本,都存在這個問題。項目截止到2019/9 作者都還在更新,最好的方法當然是自己下載下傳源碼編譯一個,也是非常簡單的。

基于源碼2.x分支最新版代碼(5 Sep 2019)編譯好資源已經上傳,md5為ec185c22e87038f5082784e541d19fe0

  • dex-tools-2.1-SNAPSHOT.zip

如果想自己編譯的話,dex2jar源碼位址:https://github.com/pxb1988/dex2jar.git,步驟如下

#安裝gradle
brew install gradle
# 編譯源碼
git clone https://github.com/pxb1988/dex2jar.git
cd dex2jar
gradle clean distZip
# if build successfull, the zip file is under dex-tools/build/distributions/
           

編譯成功後,腳本會出現在

dex-tools/build/distributions/

目錄下,是一個zip檔案,解壓後就是各種工具

dex2jar 和 jd-gui
貼上原作者的回複
notice the line

invoke-static { v0, p1 }, Lcom/twitter/android/TweetActivity;->a(Lcom/twitter/android/TweetActivity;I)Z

.

p1

is defined as

Z

(boolean) but used as

I

(int)

the problem is caused by strict type calculation, because in java syntaxt, a boolean can not assign to an inteager. so dex2jar forbid merge type

Z

and

I

. It is simple to fix
  • modify the dex by hand and add the following code before

    invoke-static { v0, p1 }, Lcom/twitter/android/TweetActivity;->a(Lcom/twitter/android/TweetActivity;I)Z

    if-eqz p1, :LZERO
        const p1, 1
        goto :Lend
    :LZERO
        const p1, 0
    :Lend
               
  • OR modify the dex2jar code. return Type I when merge I and Z at com.googlecode.dex2jar.ir.TypeClass.merge(TypeClass.java:100)

Q1:dex2jar解析應用有時候正常,有時候會報OOM的錯誤?

Java中的對象建立和回收:

String a; //聲明了一個變量,a為空

String a = new String(); //聲明了一個對象,同時在堆上為該對象配置設定了空間,變量存儲空間位址

String a = “XXX”; //查找對象位址,并在空間上填充了内容,不存在則建立對象存儲

注:此處的a是一個引用類型,通過a可以引用String類中的成員變量和成員方法

棧記憶體由Java自動配置設定并釋放;

堆記憶體(new建立)由Java虛拟機的自動垃圾回收器來管理。

解決辦法也是簡單粗暴,直接修改dex2jar執行腳本設定,改-Xmx參數來增加堆空間,not an elegant way。

Q2:想進一步驗證dex2jar的結果,運作jd-gui檢視jar閃退?

重新安裝jd-gui,指令是brew cask install jd-gui,安裝太慢了,放棄;

自己下載下傳源碼編譯安裝

# 下載下傳
git clone https://github.com/java-decompiler/jd-gui.git
cd jd-gui
# 編譯jar
./gradlew build
# 安裝app(optional)
./gradlew installOsxDist
           

編譯完成後,會在項目

build/libs/

目錄下生成

jd-gui-1.6.6.jar

jd-gui-1.6.6-min.jar

,輕按兩下即可運作;

如果安裝app,則會在項目

build/distributions/

目錄下生成各平台的壓縮包,解壓

jd-gui-osx-1.6.6.zip

就可以得到

JD-GUI.app

,也是輕按兩下運作。

編譯遇到的其他問題:

1、編譯過程中會重新下載下傳gradle,因為網絡問題會特别慢,方法是修改

gradle/wrapper/gradle-wrapper.properties

裡面的

distributionUrl

屬性,改為本地

.gradle/wrapper/dist/

目錄下的下載下傳好的gradle檔案路徑;

2、運作時會報一個與Java9的相容問題,重新安裝低版本的jdk折騰好久沒解決,最後發現是gradle版本不對,看原來的工程拿gradle2.4編的,于是又改成2.4的版本,終于編過了;

3、注意換了jdk版本,dex2jar又不能運作了,顯示找不到類方法

java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer;

,測試了下,果然是java版本的問題(心累),因為從jdk9之後,增加了一些新特性,可以通路某些子產品的受限類。

修改方法是找到jd-gui安裝路徑Contents目錄下的

Info.plist

,修改

VMOptions

屬性:

VMOptions=-Xms512m --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED;
           

也可以修改

universalJavaApplicationStub.sh

或者

workaround

java

屬性