Existe-t-il un moyen de forcer un chargeur de classes à charger un paquet même si aucune de ses classes n'a été chargée?

StackOverflow https://stackoverflow.com/questions/1816730

Question

Supposons qu'une base de code Java comporte un package appelé "com.example".

Au moment de l'exécution, nous pouvons obtenir ce package en appelant

Package p = Package.getPackage( "com.example" ); //(returns null)

ou même obtenir la liste de tous les packages en appelant

Packages[] ps = Package.getPackages();

Le problème est que si le ClassLoader n'a chargé aucune classe du paquet, il ne sera pas disponible pour ces appels de fonction. Nous pouvons le forcer à charger le paquet en chargeant d’abord une des classes du paquet, comme ceci:

this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
Package p = Package.getPackage( "com.example" ); //(returns non-null)

Cependant, c'est hacky et nécessite de connaître à l'avance le nom d'une classe appartenant au package.

La question est donc la suivante: existe-t-il un moyen d’obtenir une instance de Package par son nom, que le ClassLoader ait fait quelque chose ou non? Est-ce que mes hypothèses sur la façon dont le chargement de classe / les paquets semblent fonctionner dans cette situation sont exactes?

Était-ce utile?

La solution

Je suppose que vous en avez besoin, car vous devez examiner ses annotations. Autrement, vous ne voudriez pas avoir une référence à un Package dans laquelle seules les opérations accèdent aux annotations. Cela conduit à supposer que vous avez également défini un package-info.java avec quelques annotations.

Si vous cochez java.lang.Package , vous constaterez que getPackageInfo ne fait que charger la classe package-info en tant que classe ordinaire.

J'ai eu le même problème et suis venu avec cette solution.

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);
}

Autres conseils

Vous pouvez également utiliser le répertoire racine de la classe comme point de départ et parcourir tous les fichiers et sous-répertoires * .class. Cela ne fonctionnerait que si vous saviez où tous vos fichiers .class résideront auparavant.

La cause de tout cela est que Java a un chargement de classe dynamique, donc les classes peuvent être chargées au moment de l'exécution à partir d'emplacements inconnus au moment de la compilation ou même au moment du démarrage. Par conséquent, le concept d'un paquet n'est qu'un espace de noms pour les classes chargées, et non un répertoire que vous pouvez utiliser pour les rechercher.

Je crains que vos hypothèses ne soient pas valides. Les chargeurs de classes font la comptabilité des paquets lorsqu'ils chargent des classes.

Vous pouvez transmettre un caractère générique à ClassLoader.getResources et le forcer à choisir les classes d'un package, ce qui à son tour fera le travail.

Vous pouvez créer votre propre ClassLoader qui appelle definePackage , mais cela ne vous aidera pas avec les chargeurs de classe vanilla habituels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top