クラスがロードされていない場合でも、クラスローダーにパッケージを強制的にロードさせる方法はありますか?
-
08-07-2019 - |
質問
javaコードベースに" com.example"というパッケージがあるとします。
実行時に、呼び出してこのパッケージを取得できます
Package p = Package.getPackage( "com.example" ); //(returns null)
または呼び出してすべてのパッケージのリストを取得する
Packages[] ps = Package.getPackages();
問題は、ClassLoaderがパッケージからクラスをまだロードしていない場合、これらの関数呼び出しで使用できないことです。次のように、最初にパッケージ内のクラスの1つを強制的にロードすることにより、パッケージを強制的にロードできます。
this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
Package p = Package.getPackage( "com.example" ); //(returns non-null)
ただし、これはハッキングであり、パッケージに属するクラスの名前を事前に知る必要があります。
質問は-ClassLoaderが何かを行ったかどうかにかかわらず、名前でPackageのインスタンスを取得する方法はありますか?この状況でクラスローディング/パッケージがどのように機能するかについての私の仮定は正確ですか?
解決
注釈が必要なため、これが必要だと思います。それ以外の場合は、アノテーションへのアクセスを中心とした操作のみであるPackage参照は必要ありません。これは、そこにpackage-info.javaがいくつかの注釈とともに定義されているという仮定につながります。
java.lang.Package
をチェックすると、 getPackageInfo
がpackage-infoクラスを通常のクラスとしてロードするだけであることがわかります。
同じ問題があり、この解決策を思いつきました。
public static Package getPackage(String packageName) throws ClassNotFoundException {
Class.forName(packageName+".package-info"); // makes sure package info exist and that the class loader already knows about the package
return Package.getPackage(packageName);
}
他のヒント
別の方法として、クラスのルートディレクトリを開始点として使用し、すべての* .classファイルとサブディレクトリを確認することもできます。これは、すべての.classファイルの場所が事前にわかっている場合にのみ機能します。
このすべての原因は、Javaに動的なクラスローディングがあるため、実行時に、コンパイル時または起動時にも不明な場所からクラスをロードできることです。したがって、パッケージの概念は、ロードされたクラスの名前空間にすぎず、クラスの検索に使用できるディレクトリではありません。
あなたの仮定が有効ではないのではないかと思います。クラスローダーは、クラスをロードするときにパッケージの簿記を行います。
ワイルドカードを ClassLoader.getResources
に渡して、パッケージ内のクラスを強制的にピックアップし、順番に作業を行うことができます。
definePackage
を呼び出す独自のClassLoaderを作成できますが、使用中の通常のバニラクラスローダーでは役に立ちません。