Spring Loaded Code のホット アップデートの実践と原理分析 | JD Cloud テクニカル チーム

1 はじめに

コーディングの効率化と迅速な反復に関して開発者にとって困難なシナリオは次のとおりです。

  1. コードを変更した後、アプリケーションを頻繁に再起動する必要があるため、開発効率が低下します。

  2. リアルタイム デバッグ中は、コード変更の結果をすぐに確認することはできません。

  3. 大規模プロジェクトでは、再起動にかかる時間コストが比較的高くなります。

これらの問題に対応して、この記事では Spring Loaded ホット アップデート テクノロジを使用して開発効率を向上させ、コンパイルと再起動の時間を短縮する方法について詳しく説明します。Spring Loadedのホットアップデートの原理と、実際の適用プロセスで必要な操作や注意点を分析します。

2. フレームワークの紹介

Spring Loaded は、JVM の実行中にクラス ファイルの変更をリロードするための JVM エージェントですロード時にクラスを変換して、後で再ロードできるようにします。JVM の実行後に単純な変更 (メソッド本体の変更など) のみを許可する「ホット コード置換」とは異なり、  Spring Loaded ではメソッド/フィールド/コンストラクターを追加/変更/削除できます型/メソッド/フィールド/コンストラクターのアノテーションも変更でき、列挙型の値を追加/削除/変更することも可能です。

Spring Loaded は、JVM の実行中にクラス ファイルへの変更をリロードする JVM エージェントです。ロード時にクラスを変換して、後で再ロードできるようにします。JVM の実行中に単純な変更 (メソッド本体の変更など) のみを許可する「ホット コード置換」とは異なり、Spring Loaded ではメソッド/フィールド/コンストラクターを追加/変更/削除できます。型/メソッド/フィールド/コンストラクターのアノテーションも変更でき、列挙型の値を追加/削除/変更できます。

3. 使用方法

3.1 エージェントプラグインのダウンロード

https://repo1.maven.org/maven2/org/springframework/springloaded/1.2.8.RELEASE/springloaded-1.2.8.RELEASE.jar

3.2 エージェントプラグインの紹介

jvm 起動コマンドに次のパラメータを追加します。

-javaagent:/Users/you/runtime/springloaded-1.2.8.RELEASE.jar -noverify

3.3 変更と再コンパイル

コードを変更した後、Build->Recompile コマンドを実行すると、クラスの再ロードが完了した後、プログラムの実行ロジックが変更されたことがわかります。

4. 原理分析

4.1 コードコンパイル解析

まずソース コードの一部 (ターゲット フィールド、targetStatic 静的フィールド、メソッドを定義する RpcService クラス) を確認し、それをコンパイルします。

public class RpcService {
    private String target = "rpc";
    private static String targetStatic = "rpc static";
    public String say() {
        return "RpcService say hello SpringLoaded" + target;
    }
}

SpringLoadedがクラスをコンパイルした後、いくつかのトラッキングレコードフィールドが追加され、メソッドインターセプト判定が追加されます。

public static ReloadableType r$type = TypeRegistry.getReloadableType(0, 1);

public transient ISMgr r$fields;

public static final SSMgr r$sfields;

public String hello() {
    if (r$type.changed(0) == 1) {
        return r$type.fetchLatest()).say(this);
    }
    String targetNew = TypeRegistry.instanceFieldInterceptionRequired(1, "target") ? (String)r$get(this, "target") : this.target;
    return "RpcService say hello SpringLoaded" + targetNew;
}

getDeclaredField や getDeclaredMethod などの関数を使用すると、コードの実行時にクラスのメンバーやメソッドの情報を実行時に取得できますが、この時点で拡張クラスには次のフィールドとメソッドがあることがわかります。

コンパイルされたコードでは、RpcService クラスに Spring Loaded フレームワークによって追加されたいくつかの新しいフィールドとメソッドが含まれていることがわかります。

• r$type は、タイプが ReloadableType である静的変数です。このフィールドは、現在のクラスのオーバーロード可能な型を示すために使用されます。これには、現在のクラスの最新のバイトコードおよびその他の関連情報が含まれます。

  • r$get メソッドと r$set メソッドは、インスタンス フィールドの値を取得し、フィールドのインターセプトと置換を処理するために使用されます。
  • ___clinit___ メソッドは、クラスの静的初期化ブロックを実行するために使用されるメソッドです。
  • init () メソッドは、クラスのコンストラクターを処理するために使用されるメソッドです。
  • クラスが変更されたかどうかを判断するコード フラグメントが Say() メソッドに追加され、変更されている場合は、最新のオーバーロード可能な型で Say() メソッドを呼び出して結果を取得します。それ以外の場合は、元のメソッド本体の実行を続けます。メソッド本体には、ローカル変数をインターセプトする必要があるかどうかを判断するコード フラグメントも追加されます。インターセプトする必要がある場合は、r$get() メソッドを使用して非静的変数 traget の値を取得し、元の変数を置き換えます。それとともに価値を持ちます。

4.2 実行中のプロセスの分析

1. アプリケーションが起動すると、Spring Loaded はターゲット クラス パス内のすべてのクラスを検索し、ClassPreProcessor のカスタム クラス ローダーを使用してこれらのクラスをロードし、キャッシュ、変更の比較、依存関係の維持のために再定義した後、それらを TypeRegistry に保存します。

2. ファイル変更リスナー FileChangeListener を登録します。クラス ファイルが変更されると、Spring Loaded はその変更を検出し、クラス ファイルをリロードします。

3. クラスがリロードされると、Spring Loaded はクラスの署名と継承関係を比較しようとします。新しいクラス定義が以前のクラス定義と互換性がある場合、Spring Loaded は新しいクラス定義を指すようにアプリケーション内のオブジェクト参照を更新します。クラス定義。

5. まとめ

Spring-loaded は、JVM の起動時に Java のインスツルメンテーション API を使用してエージェントを指定し、ターゲット クラスがロードされる前にエージェントをインターセプトし、ASM ライブラリを通じてターゲット クラスのバイトコードを抽象構文ツリー (AST) に解析してから、 AST リビジョンを実行します。変更内容としては、メソッドの追加、削除、置換、メソッド本体の変更、フィールドの追加などが含まれ、最後に対象クラスの置換、ロジックの変更、コードのホットアップデートの実現などを行います。

6. 拡張コンテンツ

  • Jrebel も同様のホット アップデート機能を実装でき、より効率的で安定しています。ジュレベル公式サイト
  • Spring-boot-devtools も開発速度を向上させることができますが、その解決策はホット リスタートに似ています。Spring Boot Devtools Restarter の原理
  • ホットアップデート機能を自分で実装するにはどうすればよいですか? 考え方は似ていますが、実装にはそれぞれ独自の利点があります。自分でホットロードを実装するにはどうすればよいですか? 独自のクラスローダーを定義するにはどうすればよいですか?

著者: JD Retail チェン シャオ

出典: JD Cloud 開発者コミュニティ

人民大学の卒業生らが全学生の情報を盗んで美人採点サイトを構築、刑事拘束された NTアーキテクチャをベースにしたWindows版QQが正式リリース 米国は中国の利用を制限トレーニング AI モデルを提供する Amazon、Microsoft などのクラウド サービスの オープンソース プロジェクトが機能開発を停止すると発表 2023 年に最も高給の技術職であるLeaferJS がリリース: オープンソースの強力な 2D グラフィックス ライブラリである Visual Studio Code 1.80 が サポート端末画像機能 . スレッド登録数3,000万突破 「変化」 deepin、7月のApple M1データベースランキングに合わせてAsahi Linux採用 :Oracle急上昇、再びスコア拡大
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10086508