Javaのクラスマウントとネーミングスペース

6492 ワード

サマリ                                                                                        Javaのクラス・ローダはJavaのダイナミック性の核心であり、Javaのクラス・ローダ、および関連するparentについて簡単に説明します. delegationモデル,ネーミングスペース,ランタイムパッケージなどの概念を議論するとともに,学習で混同されやすい問題を議論する. 
クラスローダの機能と分類
    名前の通り、クラスローダはクラス(class)をJVMにロードするために使用されます.JVM仕様では、起動クラス・マウントとユーザー・カスタム・マウントの2種類のクラス・マウントが定義されています. class loader). 
   bootstrapは、java.lang.*などのコアクラスライブラリをマウントするためのJVM独自のクラスマウントです.Java.lang.Objectのようにbootstrapによってマウントされます. 
   Javaは抽象クラスClassLoaderを提供し、すべてのユーザー定義クラスローダがClassLoaderのサブクラスからインスタンス化されます. System Class Loaderは、JVMのインプリメンテーションによって提供される特殊なユーザーカスタムクラス・ローダであり、プログラミング者がローダを特に指定しない場合にデフォルトでユーザー・クラスをロードします.システムクラス・ローダはClassLoader.getSystemClassLoader()を使用できます. 方法を得る.
例1では、あなたが使用しているJVMのClassLoaderをテストします.
/*LoaderSample1.java*/
public class LoaderSample1 {
    public static void main(String[] args) {
        Class c;
        ClassLoader cl;
        cl = ClassLoader.getSystemClassLoader();
        System.out.println(cl);
        while (cl != null) {
            cl = cl.getParent();
            System.out.println(cl);
        }
        try {
            c = Class.forName("java.lang.Object");
            cl = c.getClassLoader();
            System.out.println("java.lang.Object's loader is " + cl);
            c = Class.forName("LoaderSample1");
            cl = c.getClassLoader();
            System.out.println("LoaderSample1's loader is " + cl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

私のマシンに Java 1.5)の実行結果C:/java>java LoaderSample 1 [email protected][email protected]'s loader is nullLoaderSample1's loader is sun.misc.Launcher$AppClassLoader@82ba41
最初の行は、システムクラスマウンタがクラスsun.misc.Launcher$AppClassLoaderからインスタンス化されていることを示しています. 
2行目は、システムクラスマウンタのparentがクラスsun.misc.Launcher$ExtClassLoaderからインスタンス化されていることを示します. 
3行目は、システムクラスマウントparentのparentがbootstrapであることを示します. 
4行目は、コアクラスjava.lang.Objectがbootstrapによってマウントされていることを示します. 
5行目によると、ユーザークラスLoaderSample 1はシステムクラスマウンタによってマウントされている 
parent delegationモデル
   1.2バージョンから、Javaは親委託モデルを導入し、Javaプラットフォームの安全をよりよく保証します.このモデルでは、マウントがクラスのマウントを要求されると、まず自分のparentにマウントを依頼し、parentがマウント可能であれば、このクラスに対応するClassオブジェクトを返し、parentがマウントできない場合はparentのリクエスト者によってマウントされます.
   図1に示すように、loader 2のparentはloader 1、loader 1のparentはsystem class loader.loader 2がクラスMyClassをマウントするように要求された場合、parent delegationモデルの下で、loader 2はまずloader 1にマウントを要求し、loader 1はシステムクラスマウントにMyClassのマウントを要求する.システム・マウントが正常にマウントされると、MyClassに対応するClassオブジェクトのreferenceがloader 1に戻され、loader 1がloader 2に戻り、クラスMyClassが仮想マシンにマウントされることに成功します.システムクラスのマウントがMyClassをマウントできない場合、loader 1はMyClassをマウントしようとし、loader 1もマウントに成功しない場合、loader 2はマウントを試行します.すべてのparentおよびloader 2自体がマウントできない場合は、マウントに失敗します.
   正常にマウントできるクラスマウントがある場合は、実際にマウントされたクラスマウントを定義クラスマウントと呼び、クラスマウントの定義を含むクラスマウントに正常に戻るすべてのマウントを初期クラスマウントと呼びます.図1に示すように、loader 1が実際にMyClassをマウントしているとすると、loader 1はMyClassの定義クラスマウントであり、loader 2およびloader 1はMyClassの初期クラスマウントである.
図 1 parent delegationモデル
   注意しなければならないのは、Class Loaderはオブジェクトで、その親子関係はクラスの親子関係とは何の関係もありません.親子loaderのペアは、同じClassからインスタンス化されるか、そうでないか、親loaderが子クラスからインスタンス化され、子loaderが親クラスからインスタンス化される場合もあります.MyClassLoaderがParentClassLoaderから継承されていると仮定すると、次の親子loaderがあります.
ClassLoader loader1 = new MyClassLoader();
//   loader1   parent
ClassLoader loader2 = new ParentClassLoader(loader1); 
                        

    ではparent delegationモデルはなぜより安全になったのですか?このモデルの下でユーザがカスタマイズしたクラス・ローダは、親ローダによってロードされるべき信頼性の高いクラスをロードすることができないため、親ローダによってロードされる信頼性のあるコードの代わりに、信頼性のないコードや悪意のあるコードをロードすることを防止する.実際,クラスローダの作成者はリクエストをparentに委任しなくても自由に選択できるが,前述したように安全な問題をもたらす.
ネーミングスペースとその役割
   各クラス・マウンタには独自のネーミング・スペースがあり、ネーミング・スペースは、このマウンタを初期クラス・マウンタとするすべてのクラスから構成されます.異なるネーミングスペースの2つのクラスは表示されませんが、クラスに対応するClassオブジェクトのreferenceが得られる限り、別のネーミングスペースのクラスにアクセスできます.
   例2は、1つのネーミングスペースのクラスが別のネーミングスペースのクラスをどのように使用するかを示す.例では、LoaderSample 2はシステムクラスローダによってロードされ、LoaderSample 3はカスタムローダloaderによってロードされ、2つのクラスは同じネーミングスペースにはありませんが、LoaderSample 2はLoaderSample 3に対応するClassオブジェクトのreferenceを取得するので、LoaderSample 3の共通のメンバー(age)にアクセスできます.
例2  異なるネーミングスペースのクラスへのアクセス
/*LoaderSample2.java*/
import java.net.*;
import java.lang.reflect.*;
public class LoaderSample2 {
    public static void main(String[] args) {
        try {
            String path = System.getProperty("user.dir");
            URL[] us = {new URL("file://" + path + "/sub/")};
            ClassLoader loader = new URLClassLoader(us);
            Class c = loader.loadClass("LoaderSample3");
            Object o = c.newInstance();
            Field f = c.getField("age");
            int age = f.getInt(o);
            System.out.println("age is " + age);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
/*sub/Loadersample3.java*/
public class LoaderSample3 {
    static {
        System.out.println("LoaderSample3 loaded");
    }
    public int age = 30;
}

コンパイル:javac LoaderSample2.java; javac sub/LoaderSample3.java
実行:java LoaderSample2
LoaderSample3 loaded
age is 30
                        

実行結果から、クラスLoaderSample 2に別のネーミングスペースにあるクラスLoaderSample 3のオブジェクトを作成し、共通メンバーageにアクセスできることがわかります.
ランタイムパッケージ package)
    同じクラスのマウント定義でマウントされた同じパッケージに属するクラスからランタイムパッケージが構成され、2つのクラスが同じランタイムパッケージに属するかどうかを決定します.パッケージ名が同じかどうかだけでなく、クラスマウントが同じかどうかも確認します.同じランタイムパケットに属するクラスのみが、パケットが表示されるクラスとメンバーに相互にアクセスできます.このような制限は、ユーザ自身のコードがコアクラスライブラリのクラスになりすましてコアクラスライブラリパッケージにメンバーが表示される場合を回避する.ユーザー自身がクラスjava.lang.Yesを定義し、ユーザー定義のクラス・マウントを使用するとします.java.lang.Yesとコア・クラス・ライブラリjava.lang.*は異なるマウントによってマウントされ、異なるランタイム・パッケージに属しているため、java.lang.Yesはコア・クラス・ライブラリjava.langのクラスのパッケージに表示されるメンバーにアクセスできません. 
まとめ
   クラスマウンタ,parentについて簡単に論じた. delegationモデル、ネーミングスペース、ランタイムパッケージを実行した後、それらの役割について一定の理解があると信じています.ネーミングスペースは異なる空間に属するクラスの相互アクセスを完全に禁止していないが,親委託モデルはJavaのセキュリティを強化し,ランタイムパケットはパケット可視メンバーの保護を増やした.
 
 
 
ClassLoaderのファイルの詳細:http://pickup.mofile.com/8381816404125746