Android 起動の最適化 - クラスのプリロード

バックグラウンド

Android のさまざまな最適化の中で、避けられないものの 1 つは起動の最適化です。最適化のほとんどは、遅延読み込みや特定のリソースのプリロードなど、ビジネスに関連することがよくあります。今日はビジネス関連ではなく、ロード クラスについてのみ説明します。 jvm からの最適化 論理的に独立しており、実装が比較的簡単であるため。

クラスロード

Androidのクラスロードについて簡単に説明すると、dexパッケージから対応するクラスをメソッド領域にロードすることを指し、このクラスオブジェクトは後で使用できます。このクラス ロード メカニズムは、プラグインおよびホットフィックス メカニズムを派生するためにも使用されます。

クラスローダー

jvm の親委任メカニズムについては、ここでは簡単には説明しません。

  1. BootClassLoader は Framework クラスをロードします。

  2. PathClassLoader デフォルトの ClassLoader は、システム (/data/app) にインストールされている apk をロードする役割を果たします。そのコンストラクターでは、dexPath と libraryPath (ネイティブ ライブラリ パス) の受け渡しのみが許可されます。

  3. DexClassLoader は、異なるパスに制限なく dex パッケージをロードできます。DexClassLoader は、プラグインとホット フィックスの基礎です。コンストラクターは dexPath、libraryPath、optimizedDirectory (dex2oat キャッシュ パス) を渡すことができ、dex2oat 操作により ELF ファイルが生成されます。プラグイン (AOT) の dex を最適化するには、optimizedDirectory パラメーターを使用します。

クラスロードのタイミング

画像.png

どのクラスがより時間のかかるかを知る方法

オンライン段階では、Class#findClass で多くの ANR が発生することが判明しましたが、時間のかかるクラスを事前に適切なタイミングで非 UI スレッドにプリロードできれば、ANR の確率も減らすことができます。

Hook ClassLoader を使用して、オフライン/オンラインでどのクラスに時間がかかっているかをカウントできます。

/**
 * 统计loadClass耗时
 */
class LogClassLoader(dexPath: String, parent: ClassLoader) : PathClassLoader(dexPath, parent) {

    override fun loadClass(name: String): Class<*> {
        if (name.startsWith("android.") || name.startsWith("java.lang")) {
            return super.loadClass(name)
        }
        val start = System.currentTimeMillis()
        try {
            return super.loadClass(name)
        } finally {
            val cost= System.currentTimeMillis() - start
            val thread = Thread.currentThread().name
            Log.i("loadClass", "load $name thread:$thread cost: $cost")
        }
    }
} 

初期化エントリで classLoader をフックし、最終的にどのクラスが比較的時間がかかっているかをカウントできます。

fun hook(application: Application) {
    val pathClassLoader = application.classLoader
    try {
        val logClassLoader = LogClassLoader("", pathClassLoader.parent)
        val pathListField = BaseDexClassLoader::class.java.getDeclaredField("pathList")
        pathListField.isAccessible = true
        val pathList = pathListField.get(pathClassLoader)
        pathListField.set(logClassLoader, pathList)

        val parentField = ClassLoader::class.java.getDeclaredField("parent")
        parentField.isAccessible = true
        parentField.set(pathClassLoader, logClassLoader)
    } catch (throwable: Throwable) {
        Log.e("hook", throwable.stackTraceToString())
    }
} 

戦略、タイミングの最適化

  1. Class.forName をプリロードします

上記の統計により、どのクラスのロードに時間がかかっているかが分かり、適切なタイミングで対応するクラス (特に kotlin の多くのクラス) をサブスレッドでロードすることを選択できます。

Class.forName(className, true, context.classLoader) 

初期化パラメータは true に設定され、静的コード ブロックが初期化されることを示し、静的変数の割り当てなどの操作が行われます。

  1. VerifyClass を無効にする

ClassLoader#loadClass プロセスでは、defineClass (dex パッケージ io からクラスをロード)、verifyClass (命令を検証)、resolveClass (クラスのリンク、フィールド メモリの割り当て)、および init (静的変数とコード ブロックの初期化) を通過する必要があります。

Systrace や perfetto ツールを使用してロード時間を確認すると、その中でも VerifyClass に時間がかかります。

プラグイン

現在、主要メーカーのアプリは基本的にすべて WeChat や Douyin などのプラグインを使用しています。プラグインには、プラグインのクラス class、リソース resource、プラグインの so のロードという重要なポイントがいくつかあります。

次のような落とし穴もたくさんあります。

  • 異なるクラスローダーは異なる名前空間をロードするため、プラグインの相互依存性などに問題があります。

  • プラグインの ClassLoader とメイン パッケージの ClassLoader がメイン パッケージとプラグイン パッケージのクラスをロードし、また、同じクラスが異なる classLoader によって繰り返しロードされないようにするにはどうすればよいですか。

  • プラグイン dex パッケージには dex2oat がありません。通常、dex2oat 操作 (AOT) を実行する追加プロセスを開きます。コンパイルおよび最適化後、プラグイン ClassLoader の最適化ディレクトリとして設定できますが、8.0 以降では、 BaseDexClassLoader の最適化されたディレクトリ パラメータは役に立ちません。これは、プラグイン AOT が無効であることを意味します。

  • Android 5.0 より前では、AOT はインストール中に完全にコンパイルされるため、非常に遅くなりますが、Android 7.0 以降は、JIT と AOT が使用されるため、起動時に AOT が開始される可能性があります。最適化方法の 1 つは、AOT を抑制または遅延することです。 ANR、起動速度を最適化します。

まずは上部の穴を残して、後で整理されるのを待ちましょう。

要約する

アーキテクトになりたい場合は、コーディングとビジネスに限定されず、モデルを選択し、拡張し、プログラミング的思考を向上させることができなければなりません。また、しっかりとしたキャリアプランも大切で、学ぶ習慣も大切ですが、一番大切なのは継続力であり、継続的に実行できないプランは絵にかいたもちです。

方向性がわからない場合は、Ali のシニア アーキテクトが書いた一連の「Android の 8 つの主要モジュールに関する上級ノート」をここで共有したいと思います。これは、乱雑で散在し断片化した知識を体系的に整理するのに役立ちます。 Android開発のさまざまな知識を体系的かつ効率的に習得できます。
ここに画像の説明を挿入
私たちが普段読んでいる断片的な内容と比べて、このノートの知識ポイントはより体系的で理解しやすく、覚えやすく、知識体系に従って厳密に配置されています。

1. 建築家に必須のスキル

1. Java ジェネリックの深い理解
2. 簡単な言葉での注釈
3. 同時プログラミング
4. データ送信とシリアル化
5. Java 仮想マシンの原則
6. 効率的な IO
...

ここに画像の説明を挿入

2. Android フレームワーク トップ 100 のソース コード分析

1.Retrofit 2.0 ソース コード
分析2.Okhttp3 ソース コード分析
3.ButterKnife ソース コード分析4.MPAndroidChart
ソース コード分析
5.Glide ソース コード分析6.Leakcanary
ソース コード
分析7.Universal-lmage-Loader ソース コード分析
8.EventBus 3.0 ソース コード分析
9.zxing ソースコード解析
10. Picasso ソースコード解析
11. LottieAndroid 使い方の詳細説明とソースコード解析
12. Fresco ソースコード解析 - 画像読み込み処理

ここに画像の説明を挿入

3. Androidのパフォーマンス最適化の実際の分析

  • Tencent のバグ: 文字列照合アルゴリズムについて少し理解する
  • iQiyi: Android APP クラッシュ キャプチャ ソリューション - xCrash
  • ByteDance: Gradle フレームワークの 1 つ (プラグイン、拡張機能、buildSrc) についての深い理解
  • Baidu APP テクノロジー: Android H5 の最初の画面最適化の実践
  • Alipay クライアント アーキテクチャの分析: Android クライアントの起動速度の最適化「ガベージ コレクション」
  • Ctrip: Zhixing Android プロジェクトからコンポーネント アーキテクチャの実践を見る
  • Netease News 建設の最適化: 建設速度を「稲妻のように」するにはどうすればよいですか?

ここに画像の説明を挿入

4. 高度なkotlinで実戦強化

1. Kotlin 入門チュートリアル
2. Kotlin 実戦ピット回避ガイド
3. プロジェクト実戦「Kotlin Jetpack 実戦」

  • 大神を崇拝するデモから始める

  • Kotlin で Gradle スクリプトを書いた経験は何ですか?

  • Kotlin プログラミングの三重の領域

  • Kotlin の高次関数

  • Kotlin ジェネリック

  • Kotlin 拡張機能

  • Kotlin の委任

  • コルーチンの「不明な」デバッグ手法

  • グラフィカルコルーチン: サスペンド

ここに画像の説明を挿入

5. Android 高度な UI オープンソース フレームワークの高度な復号化

1. SmartRefreshLayout の使用
2. Android PullToRefresh コントロールのソース コード分析
3. Android-PullToRefresh プルダウン更新ライブラリの基本的な使用方法4. LoadSir -
効率的で使いやすい読み込みフィードバック ページ管理フレームワーク ( 7. Hellocharts- android 使用ガイド8. SmartTable 使用ガイド9. オープンソース プロジェクト android-uitableview の紹介10. ExcelPanel 使用ガイド11. Android オープンソース プロジェクト SlidingMenu の詳細分析12. MaterialDrawer 使用ガイド








ここに画像の説明を挿入

6. NDKモジュール開発

1. NDK モジュール開発
2. JNI モジュール
3. ネイティブ開発ツール 4.
Linux プログラミング
5. 低レベル画像処理
6. オーディオおよびビデオ開発
7. 機械学習

ここに画像の説明を挿入

7. 高度なフラッターテクノロジー

1. Flutter クロスプラットフォーム開発の概要
2. Windows での Flutter 開発環境の構築
3. 初めての Flutter APP の作成
4. Flutter 開発環境の構築とデバッグ
5. Dart 文法の基本文法 (1)
6. Dart 文法の一部コレクションの利用とソースコード解析(2)
7. コレクション演算子関数とDart構文のソースコード解析(3)
...
ここに画像の説明を挿入

8. Wechat ミニプログラムの開発

1. 小さなプログラムの概要と紹介
2. 小さなプログラムの UI 開発
3. API の操作
4. ショッピング モール プロジェクトの戦闘...

ここに画像の説明を挿入

ビデオ素材のフルセット:

1. インタビュー集
ここに画像の説明を挿入
2. ソースコード解析集

ここに画像の説明を挿入
3. オープンソースフレームワークのコレクション

ここに画像の説明を挿入
ワンクリックと 3 つのリンクで皆さんのサポートを歓迎します。記事内の情報が必要な場合は、記事の最後にある CSDN 公式認定 WeChat カードをクリックするだけで無料で入手できます [100% 無料を保証します] ↓↓↓
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/m0_56255097/article/details/125286576#comments_27467446