LoginSignup
1
1

More than 5 years have passed since last update.

ProGuardで-dontoptimizeを使いたくないから作った何か

Last updated at Posted at 2017-10-09

はじめに

結論

はじめに

こんなエラー見たことありませんか?

Unexpected error while computing stack sizes:
  Class       = [com/google/android/gms/internal/zzgr]
  Method      = [run()V]
  Exception   = [java.lang.IllegalArgumentException] (Stack size becomes negative after instruction [166] pop in [com/google/android/gms/internal/zzgr.run()V])
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Stack size becomes negative after instruction [166] pop in [com/google/android/gms/internal/zzgr.run()V]

Support Libraryとかgms更新すると-dontoptimize無しには難読化はできなくなってしまいます。
でも使いたい! 1

もちろん、

-keep class com.google.android.gms.internal.zzgr { *; }

は効きません。
ProGuard改造なんてしてもまともに動かない。

でも結局諦めるしか...と思いつつ考えていたら、ある結論にたどり着きました。

ProGuardを2回やればいいんだ

Transform API

AndroidのGradleプラグインには、Transform APIなるものがあります。2
詳細については省きますが、これにはProGuardで難読化する部分があります。3

優先順位は選べない

GradleにはdependsOnみたいにTaskの順番を左右する指定をすることができますが、Transform APIが崩壊するのは間違いないので使わないことにしました。
また、android.registerTransformはTransformの順番を変えられないので、途中に挿入することは諦めました。

改造

じゃあTransform自体を改造すればいいじゃない!
Transformをなんとか改造すれば、ProGuardを起動するまでの部分に手を加えることができます。
TransformTaskがガバガバだったこともあり4これだ!と一瞬閃きました。
ですがJVMの仕様上、一度読み込まれたクラスは書き換えられません。
書き換えるのではなく、継承をしつつ、TransformTaskにはフィールドの読み書きで対応することにしました。

意外とコピペでもエラーは多く出ないんですね。びっくりしました。

2段階ProGuardって一体何してるの?

1段階目

ユーザーの指定したProGuard設定を少し変更し、入力ファイルの組成を変更して難読化をします。

ProGuard設定の変更内容

-keep class **.R { *; } # 追加
-keep class **.R$** { *; } # 追加

libraryJars
- android.jarと愉快な仲間たち
- jarファイル(大体ライブラリです)
inJars
- ディレクトリのクラスファイル群(大体プロジェクトに属するコードです)

inJarsからライブラリを排除することが重要で、これをすれば難読化ができます。

2段階目

ユーザーの指定したProGuard設定を少し変更し、入力ファイルの組成を再変更して難読化をします。

ProGuard設定の変更内容

-dontoptimize # 追加

libraryJars
- android.jarと愉快な仲間たち
inJars
- 1段階目でのjarファイル(1段階目の時点では変わっていません)
- 1段階目で吐き出したjarファイル

ここまでの時点ですべての入力クラスファイルが全てProGuardによって処理されます。
エラー? 出ませんよ5

最後に

ここまでご覧いただきありがとうございました。
ソースコードはここに置いておいたので、改変するなりPRするなりIssueするなりご自由に。
そしてJitPack.ioって便利ですね



  1. -dontoptimizeの使用が推奨されている模様。仕方ないね 

  2. transformで始まるTaskがTransform APIによるものです。 

  3. https://github.com/nao20010128nao/android-gradle-plugin-source-codes/blob/master/gradle-core-2.4.0-alpha7-sources/com/android/build/gradle/internal/transforms/ProGuardTransform.java 

  4. 面白いことにTransformTasktransformフィールドはfinalではないのでリフレクションで触れるんです。 

  5. 少なくとも投稿者の環境では、ですが。 

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1