目次 | 前項目 | 次項目 Java コアリフレクション


概要

Java(TM) コアリフレクション API は、現在の Java 仮想マシン内のクラスやオブジェクトに関する内部情報の参照と変更をサポートする、小規模で、型に関する安全性の保証された API を提供します。セキュリティポリシーで認められる場合、API を使って次のことを実行できます:

コアリフレクション API が定義する新規クラスおよびメソッドは、次のとおりです:

リフレクションをサポートする java.lang パッケージにも、次の内容が追加されました:

アプリケーション

コアリフレクション API を使うと、次のような 2 種類のアプリケーションが作れるようになります。

1 つは、実行クラスに基づくターゲットオブジェクトの、すべての public メンバを見つけ出して使う必要があるアプリケーションの集合です。これらのアプリケーションは、オブジェクトのすべての public フィールド、メソッド、および構築子に実行時にアクセスする必要があります。このカテゴリに入るアプリケーションには、Java(TM) Beans[1]、あるいはオブジェクトインスペクタなどの簡易ツールがあります。これらのアプリケーションは、クラス Class のメソッド getField, getMethod, getConstructor, getFields, getMethods, および getConstructors から獲得したクラス Field, Method, および Constructor のインスタンスを使います。

もう 1 つは、所定クラスが宣言したメンバを見つけ出して使う必要のある、複雑なアプリケーションの集合です。これらのアプリケーションは、class ファイルが指定したレベルのクラス実装への実行時アクセスが必要です。このカテゴリに入るアプリケーションには、デバッガ、インタプリタ、インスペクタ、クラスブラウザなどの開発ツールや、Java(TM) オブジェクト直列化[2] などの実行サービスがあります。これらのアプリケーションは、クラス Class のメソッド getDeclaredField, getDeclaredMethod, getDeclaredConstructor, getDeclaredFields, getDeclaredMethods, および getDeclaredConstructors から獲得したクラス Field, Method, および Constructor のインスタンスを使います。


リフレクションモデル

3 つのクラス Field, Method, および Constructorfinal です。これらのクラスのインスタンスを生成できるのは、Java 仮想マシンだけです。これらのオブジェクトを使って基本オブジェクトを操作します。つまり:

インスタンスの生成できない final クラス Array には、新規配列の作成、配列要素の獲得と設定を行えるようにする static メソッドが備わっています。

Member インタフェース

クラス Field, Method および Constructor は、Member インタフェースを実装します。クラス Member のメソッドを使って、基本の識別情報に関する反射されたメンバを問い合わせます。識別情報には、メンバを宣言したクラスまたはインタフェース、メンバ名、およびメンバの Java 言語修飾子 (public, protected, abstract, synchronized など) が含まれます。

Field オブジェクト

Field オブジェクトは、反射されたフィールドを表します。基本フィールドはクラス変数 (static フィールド) でもインスタンス変数 (非 static フィールド) でも構いません。クラス Field のメソッドを使って、基本フィールドの型を獲得し、オブジェクトの基本フィールド値を入手して設定します。

Method オブジェクト

Method オブジェクトは、反射されたメソッドを表します。基本メソッドは、abstract メソッド、インスタンスメソッド、クラス (static) メソッドのどれでも構いません。

クラス Method のメソッドを使って、基本メソッドの形式パラメータ型、返却値の型、および確認済み例外の型を獲得します。また、クラス Methodinvoke メソッドを使って、ターゲットオブジェクトの基本メソッドを呼び出します。インスタンスおよび abstract メソッドの呼出しでは、ターゲットオブジェクトの実行クラスならびに反射されたメソッドの宣言クラス、名前、および形式パラメータ型に基づいた動的なメソッド解決法を使います。(従って、インタフェースを実装するクラスのインスタンスであるオブジェクトについて、反射されたインタフェースメソッドを呼び出すことが可能です)。メソッド呼出しでは、メソッドの宣言クラスの基本 static メソッドを使います。

Constructor オブジェクト

Constructor オブジェクトは、反射された構築子を表します。クラス Constructor のメソッドを使って、基本構築子の形式パラメータ型と確認済みの例外の型を獲得します。さらに、クラスがインスタンスを実行できる場合は、クラス ConstructornewInstance メソッドを使って、構築子を宣言するクラスの新規インスタンスを生成して初期化します。

Array および Modifier クラス

Array クラスはインスタンスを生成できないクラスです。これはクラスメソッドをエクスポートして、プリミティブまたはクラスコンポーネント型の Java 配列を生成します。クラス Array のメソッドを使って、配列を構成する値の獲得と設定も行います。

Modifier クラスはインスタンスを生成できないクラスです。これはクラスメソッドをエクスポートして、クラスやメンバの Java 言語修飾子を解読します。言語修飾子は、Java 仮想マシン仕様で定義のコード化定数を使って整数型にコード化します。

プリミティブ Java 型の表現

最後に、新規 Class オブジェクトが 9 つあります。これらのオブジェクトを使って、8 つのプリミティブ Java 型と void を実行時に表現します。(これらは Class オブジェクトであって、クラスではないことに注意してください。)コアリフレクション API はこれらのClassオブジェクトを使って、次のものを識別します:

Java 仮想マシンは、これらの 9 つの Class オブジェクトを生成します。これらのオブジェクト名は、それぞれが表す型と同じです。Class オブジェクトは、次の public final static 変数を介してのみ参照できます:

    

        java.lang.Boolean.TYPE

        java.lang.Character.TYPE

        java.lang.Byte.TYPE

        java.lang.Short.TYPE

        java.lang.Integer.TYPE

        java.lang.Long.TYPE

        java.lang.Float.TYPE

        java.lang.Double.TYPE

        java.lang.Void.TYPE

特に、これらの Class オブジェクトは、クラス ClassforName メソッドからはアクセスできません。


セキュリティモデル

Java セキュリティマネージャは、クラス単位でコアリフレクション API へのアクセスを制御します。セキュリティを安全に施行するには、次の 2 つのレベルを確認する必要があります:

ポリシー決定は、クラス SecurityManager の新規メソッドである checkMemberAccess メソッドで行います。

void checkMemberAccess(Class,int) throws SecurityException

第 1 パラメータは、アクセスが必要なメンバを持つクラスやインタフェースを指定します。第 2 パラメータはアクセスされるメンバセット (Member.PUBLIC または Member.DECLARED のいずれか) を指定します。

指定クラスの指定メンバセットへのアクセス要求が拒否されると、メソッドは SecurityException をスローします。セットへのアクセスが付与されると、メソッドは返ります。

既に説明したように、このセットの反射されたメンバを使って以下のような基本オブジェクトの操作を行うときは、標準の Java 言語アクセス制御が実行されます:

この時点でアクセスが拒否されると、反射されたメンバは IllegalAccessException をスローします。

Java 言語ポリシー

アプリケーションに関する Java 言語セキュリティポリシーは、任意のコードが、リンクする先の任意のクラスのすべてのメンバおよび構築子 (非 public メンバと構築子を含む) への反射的アクセスを獲得できるということです。メンバまたは構築子への反射的アクセスを獲得するアプリケーションコードが反射された再帰メンバまたは構築子を使うことができるのは、標準の Java 言語アクセス制御がある場合だけです。

JDK 1.1 のセキュリティポリシー

Sun の Java Development Kit 1.1 (JDK1.1) は、言語仕様には含まれない独自のセキュリティポリシーを実装しています。Sun の JDK1.1 では、クラス AppletSecurity が以下のポリシーを実装します:

メンバへの反射的アクセスを獲得するコードは、標準の Java 言語アクセス制御がある場合にのみ、このアクセスを使うことができます。特権コードの概念はないので、標準の言語アクセス制御チェックをオーバーライドする手段はありません。

このポリシーは、安全性が保障されないコードに関しては厳密で、Java 仮想マシンのリンカよりも厳しく限定されます。例えば、安全性が保障されないクラスだけでは、リフレクション経由でシステムスーパークラスの protected メンバにアクセスできません。これに対して、リンカ経由ではアクセス可能です。(ただし、システムコードがこのようなメンバにアクセスして、メンバを信頼されないコードに渡すことはできます)。

JDK のセキュリティポリシーは、今後 Java のセキュリティフレームワークに発展していくと期待されています。


データ変換

リフレクションパッケージの特定メソッドは、プリミティブ型とクラス型オブジェクト間のデータ変換を自動実行します。フィールドおよび配列のコンポーネント値を獲得/設定するための一般メソッド、ならびにメソッドと構築子呼出しのためのメソッドがあります。

自動データ変換には次の 2 つの型があります。ラッピング変換は、プリミティブ型からクラス型オブジェクトの値に変換します。アンラッピング変換は、クラス型オブジェクトからプリミティブ型の値に変換します。これらの変換に関する規則は、「ラッピング変換とアンラッピング変換」で定義します。

さらに、フィールドアクセスとメソッド呼出しは、プリミティブ型および参照型について拡張変換を可能にします。これらの変換については、Java 言語仕様のセクション 5 を参照してください。より詳細な情報は、「拡張変換」 を参照してください。

ラッピング変換とアンラッピング変換

プリミティブ値は、 Field.get または Array.get で獲得したり、Method.invoke から呼び出したメソッドによって返されると、自動的にオブジェクトにラップされます。

同様にオブジェクト値は、プリミティブ型の値を必要とする、以下のコンテキストのパラメータとして提供されると、自動的にアンラップされます:

以下は、プリミティブ型とクラス (ラッパ) 型の対応表です:

boolean java.lang.Boolean
char java.lang.Character
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double

void 宣言されるメソッドは、Method.invoke から呼び出されると、null を返します。

拡張変換

リフレクションパッケージでは、コンパイル時にメソッド呼出しコンテキストで認められるものと同じ拡張変換が可能です。これらの変換は、Java 言語仕様のセクション 5.3 で定義されます。

拡張変換は、以下の実行時に行われます:

認められる拡張変換には、次のものがあります:

認められる 拡張参照変換には次のものがあります:


パッケージング

コアリフレクション API は、java.langjava.lang.reflect という名前の新規サブパッケージにあります。Java の既定パッケージのインポート規則に触れて互換性の問題が発生することはありません。



目次 | 前項目 | 次項目
Copyright (C) 1996, 1997 Sun Microsystems, Inc. All rights reserved.