Javaクラスのロードに関する各方面について話します

3425 ワード

クラスローダとは
クラスローダは、クラスの説明を仮想マシンメモリにロードするモジュールです.典型的なクラスの説明はjavaソースコードのコンパイル後のclassファイルであり、ネットワークバイトストリームなどの他の任意のデータ形式であってもよい.
クラス・ローダにはどのようなものがありますか.
JAvaのデフォルトでは、3種類のローダが定義されています.
  • 起動クラスローダ(Bootstrap Class-Loade)主にjre/libの下のjarパケット
  • をロードする
  • 拡張クラスローダ(Extension or Ext Class-Loader)は主にjre/lib/ext/ディレクトリのjarパッケージをロードします.(jre/lib/ext/ディレクトリは、指定したjava.ext.dirsで上書きできます)
  • アプリケーションクラスローダ(Application or App Class-Loader)は、classpathのコンテンツをロードします(classPathはディレクトリのセットです).

  • アプリケーションクラスローダは、-Djava.system.class.loader=com.yourcorp.YourClassLoaderのパラメータ全体を使用して、既存のアプリケーションクラスローダを上書きできます.ここのオーバーライドには二重引用符が付けられており、実際にカスタマイズされたクラスローダはデフォルトのアプリケーションクラスローダの父親と呼ばれます.
    一般的には、両親の委任モデルを変える必要がある場合にそうします.親委任モデルについては、以下を参照してください.
    クラス・ローダの親委任モデル
    親委任モデルとは
    クラス・ローダ(Class-Loader)がタイプをロードしようとすると、親ローダが対応するタイプが見つからない場合を除き、このタスクを現在のローダの親ローダにできるだけ代理します.委任モデルを使用する目的は、Javaタイプの重複ロードを回避することです.
    なぜ親委任モデルを採用するのか
    親委任モデルの採用は主に2つの点から考えられる.
  • はクラスの一意性を保証し、1つのクラスは1回しかロードされず、重複ロードを避ける.(JVM仕様では同じclassファイルが2つの同じクラスにロードされるため、2つのクラスとみなされる)
  • セキュリティ、javaコアAPIが置き換えられないことを保証する.すなわち、起動クラスローダがロードしたクラスは他のクラスローダによって上書きされない.

  • 両親の委任モデルを破ったのはどれですか.なぜ破ったのですか.
  • JNDIサービス
  • Tomcatサーバ
  • OSGIは熱更新
  • を実現する.
    以上のシーンが親委任モデルを破ったのは、親が必要な論理をロードまたは完了する能力がないためであり、全体的なアーキテクチャ設計がより優雅で柔軟になるために、サブクラスローダに渡してロードを行う.
    クラス・ロードのプロセス
    クラスのロードは主に3つのプロセスに分けられ、ロード、リンク、初期化;
    ロード:Javaはバイトコードデータを異なるデータソースからJVMに読み込み、JVMが認可するデータ構造(Classオブジェクト)にマッピングします.
    リンク:これはコアのステップで、簡単に言えば元のクラス定義情報をJVM実行中にスムーズに変換します.具体的には検証、準備、解析の3つの過程に細分化されている.
  • 検証:Classオブジェクトが仮想マシン仕様
  • に準拠していることを確認します.
  • 準備:静的変数を作成し、メモリ領域
  • を準備します.
  • 解析:定数プール内のシンボル参照を直接参照
  • に変更
    初期化:静的フィールド付与、静的ブロックの初期化など、クラスの初期化ロジックを実行します.親タイプの初期化は、現在のタイプよりも優先されます.
    カスタムクラスローダの適用シーン
  • クラスのバイトコードロジックを修正します.例えば、外部クラスのために汎用ロジックを統一的に織り込む;
  • ユーザーのニーズに応じて、動的にクラスを作成します.例えば、JDBCの駆動クラスは、異なるデータベースで異なる駆動クラス
  • を使用する必要がある.
  • パッケージ名+クラス名が競合している場合、1つのクラスローダは同時にロードできず、異なるクラスローダでメモリにロードできます.
  • 熱更新特性は、クラスローダをカスタマイズすることにより、実行中にクラス
  • を動的にロード、アンインストールすることを実現する.
    カスタムクラスローダの実装
    主な核心はクラスのバイトコードを取得する段階であり、バイトコードをClassオブジェクトにマッピングする場合、この部分は一般的に関与しない.
    public class CustomClassLoader extends ClassLoader {
     
        @Override
        public Class findClass(String name) throws ClassNotFoundException {
            byte[] b = loadClassFromFile(name); //       
            return defineClass(name, b, 0, b.length);
        }
     
        private byte[] loadClassFromFile(String fileName)  {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
                    fileName.replace('.', File.separatorChar) + ".class");
            byte[] buffer;
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            int nextValue = 0;
            try {
                while ( (nextValue = inputStream.read()) != -1 ) {
                    byteStream.write(nextValue);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            buffer = byteStream.toByteArray();
            return buffer;
        }
    }

    小結
    今日はjavaクラスのローダについて、以下の知識を共有しました.
  • クラスローダ
  • とは
  • 類のローダは具体的にどれらの
  • があります
  • クラスロード中の親委任モデル
  • クラスロードの具体的なプロセス
  • カスタムクラスローダのアプリケーションシーン
  • クラスのローダの実装
  • ゼロの基礎はJavaのプログラミングを学んで、私の10年のJava学習パークに参加することができて、技術の交流、資源の分かち合い、質疑応答と困惑、開発の経験の総括.