- 原✓题:Androidにネイティブライブラリをロードすることの危険性
- 元のアドレス: medium.com/keepsafe-en…
- 原作者:Hilal Alsibai
- 初版発行時間:2015年11月7日
作者は昨年問題に遭遇しました:プロジェクトがapk
ファイルにパッケージ化された後、インストールは正常でした。プロジェクトがファイルにパッケージ化された後、ファイルaab
にbundleTool
解析された後にクラッシュしましたが、ファイルをアップロードした後、ファイルをダウンロードし、通常どおりにインストールします。apk
MMKV
aab
googlePlay
apk
この記事を読むことで、この問題が発生する理由とこの問題を解決する方法を理解できます。
翻訳
KeepSafeの初期2012
の頃Android
、私たちはアプリケーションに暗号化スキームを実装しようとしました。多くの反復とプロトタイプを通じて、 JNI(Java Native Interface)のパワーを活用することでスイートスポットを見つけました。暗号化と復号化の目的でのみライブラリを呼び出すことJava
により、で使用する暗号化ライブラリにインターフェイスを書き込むことにしました。JNI
ユーザーエクスペリエンスへの影響を最小限に抑えた即時ソリューションを選択しました。ソリューションに満足したら、それを本番アプリケーションにデプロイすることにしました。私たちはコードを厳密にテストし、すべてがスムーズに進むと信じていましたが、結局は制御できなくなりました。
UnsatisfiedLinkError
創発
起動後にクラッシュレポートを心配そうに更新していたので、繰り返し発生するバグに気づき始めました。ユーザーがこれに遭遇しましたUnsatisfiedLinkError
。これは、2つの可能性があることを意味します。(1)呼び出しているネイティブライブラリが存在しない、(2)呼び出しているネイティブメソッドが存在しない。2つ目は、ほとんどの場合、コンパイルと基本的なテストによって検出されるため、現時点では、ユーザーのインストールAPK
に、で提供するネイティブライブラリがないso
という事実に混乱しています。
ここにいくつかのログファイルがあります:
java.lang.UnsatisfiedLinkError: Couldn’t load stlport_shared from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.kii.safe-1.apk,libraryPath=/data/app-lib/com.kii.safe-1]: findLibrary returned null\
at java.lang.Runtime.loadLibrary(Runtime.java:365)\
at java.lang.System.loadLibrary(System.java:535)\
at com.kii.safe.Native.<clinit>(Native.java:16)\
… 63 more
Caused by: java.lang.UnsatisfiedLinkError: Library stlport_shared not found\
at java.lang.Runtime.loadLibrary(Runtime.java:461)\
at java.lang.System.loadLibrary(System.java:557)\
at com.kii.safe.Native.<clinit>(Native.java:16)\
… 5 more
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: get_lib_extents[760]: 1305 — /mnt/asec/com.kii.safe-1/lib/libstlport_shared.so is not a valid ELF object\
at java.lang.Runtime.loadLibrary(Runtime.java:434)\
at java.lang.System.loadLibrary(System.java:554)\
at com.kii.safe.Native.<clinit>(Native.java:15)
Caused by: java.lang.UnsatisfiedLinkError: Library cryptopp not found\
at java.lang.Runtime.loadLibrary(Runtime.java:461)\
at java.lang.System.loadLibrary(System.java:557)\
at com.kii.safe.Native.<clinit>(Native.java:17)
复制代码
非常に腹立たしい
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: 1748 cannot locate ‘쯰ҷЦf1Ϙ˗˞ք0Ⱉض夘Ϛ.͏闑㥁ج뭫ර⓻в^ӎ3c`+W#Ҽ?-Bַˌ֕꼠’…\
at java.lang.Runtime.loadLibrary(Runtime.java:370)\
at java.lang.System.loadLibrary(System.java:535)\
at com.kii.safe.Native.<clinit>(Native.java:17)
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1312]: 1327 cannot locate ‘Pܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭXߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭXߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#ʭX Ϛߐܝ#\
at java.lang.Runtime.loadLibrary(Runtime.java:434)\
at java.lang.System.loadLibrary(System.java:554)\
at com.kii.safe.Native.<clinit>(Native.java:17)
复制代码
so
すべてのライブラリが例外をスローしているように見えるため、ライブラリに障害がある明確なパターンはありません。これAndroid
はバージョン固有ではなく、特定のデバイスで発生するだけではありません。また、場合によっては、一部のネイティブライブラリが正しくロードされますが、すべてではありません。この時点で、私たちは必死にインターネットで答えや助けを探しますが、手ぶらで戻ってきます。修正、主に投機的な修正、クラッシュが発生したときの正確な環境をよりよく理解できるようにする追加のトレースデータ、および予想されるインストール場所にあるネイティブライブラリを具体的にチェックするコードのリリースを開始しました。
また、場合によっては、一部のネイティブライブラリが正しくロードされますが、すべてではありません。
収集した情報は、ネイティブライブラリが存在しないことを示しています。システムクラスまたはファイルシステムエラーは奇妙なまぐれではありませんが、このユーザーのデバイスは問題ないようです。私たちは次のアイデアを持っています:
(1)ユーザー機器のスペースが不足している
この例外の考えられる理由を考えたとき、おそらく人々はネイティブライブラリを適切にインストールするスペースがなかったので、インストールされなかったのではないかと考え始めました。ライブラリをロードする前の簡単な診断チェックにより、このアイデアが間違っていることがすぐにわかりました。ユーザーは、出荷するライブラリ用にデバイスに十分なスペースがあります。
(2)so
ライブラリはアップデートに含まれていません
造成我们问题的第二个可能原因是Google Play
在向用户设备提供APK
时破坏了我们的APK
。在阅读了诸如此类的报告后,我们对这个想法有了一些支持,详细说明Google Play
应该向所有受问题影响的应用程序开发人员发出通知,该问题导致用户在更新后无法启动他们的应用程序,因为本地库安装不正确。唯一的问题是这份报告是在8
月发布的,而我们在几个月后才开始处理这个问题。我们也从未收到来自Google Play
的通知,提到他们有任何错误。当然,这是很难验证的。
(3)直接与真实用户一起调试问题
由于我们无法在手头的10
多种不同设备上重现该问题,因此我们决定联系遇到问题的用户。一位用户慷慨地决定帮助我们,并指出该应用程序在最新更新之前运行良好。这里的问题是,用户注意到的应用程序版本是一个包含我们的加密代码和本机库的版本,这只是为了增加我们的困惑和总体难题。我们决定直接向用户提供一个APK
文件,我们在其中验证了所有本机库都存在于APK
文件中。用户安装了APK
,启动了应用程序,然后又直接遇到了同样的UnsatisfiedLinkError
异常。这证实了不是Google Play
的问题,问题在于Android
的PackageManager
安装过程。
找到解决方案
由于我们发现问题出在安装过程中,因此我们决定复制安装过程中提取应用程序代码中的本机库的部分。幸运的是,您可以通过以下方式轻松获取设备上应用程序APK
文件的引用
Context.getApplicationInfo().sourceDir;
复制代码
次に、これを使用してネイティブライブラリを内部ストレージの場所に抽出します。APK
ファイルは単なるファイルなので、抽出コードZIP
を書くだけです。ZIP
コードをプルして迅速に出荷することができたため、クラッシュの数が大幅に減少しました。毎日スローされるUnsatisfiedLinkError
例外に示します。
サイズを縮小APK
し、アプリケーションをすべての可能なデバイスで実行できるようにするために、、、、およびのアプリケーションを設計しましx86
た。Armv7
Arm
各フレーバーには、それぞれのアーキテクチャに対応するネイティブライブラリのみが含まれているため、デバイスアーキテクチャ用に作成されていないものを誰かがインストールする可能性は十分にありAPK
ます。
クラッシュ時にインストーラーパッケージ名のログ記録を開始しましたが、ユーザーはさまざまなソースからアプリをインストールしており、新しいアプリはすべて、ユーザーがデバイスのアーキテクチャUnsatisfiedLinkError
が間違っているために誤ってインストールした手動でインストールされたアプリからのものであることがすぐにわかりました。abi
これが最後の「落とし穴」で、とても簡単な説明で安心です。
導入ReLinker
抽出コードを、誰もが使用できる小さなライブラリにパッケージ化することにしました。特に、開発者が制御できない非常に基本的なAndroid
機能が含まれている場合は、デバッグプロセスを実行する必要はありません。App
ReLinker
標準を置き換えるのと同じくらい簡単に使用できます
System.loadLibrary(“mylibrary”);
复制代码
コールバックを使用する
ReLinker.loadLibrary(context, “mylibrary”)
复制代码
エピローグ
修正がリリースされた時点で、このクラッシュを経験している人の数は約に達し続けました100,000
。皆様のおReLinker
役に立てば幸いです。また、ランダムに遭遇することはありませんUnsatisfiedLinkerError
。