Gibt es eine Möglichkeit, einen Klassenloader zu zwingen, ein Paket zu laden, auch wenn keiner seiner Klassen geladen wurde?

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

Frage

Nehmen wir an, eine Java -Codebasis verfügt über ein Paket namens "com.example".

Zur Laufzeit können wir dieses Paket durch Anruf erhalten

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

Oder erhalten Sie sogar eine Liste aller Pakete, indem Sie anrufen

Packages[] ps = Package.getPackages();

Das Problem ist: Wenn der Klassenloader noch keine Klasse aus dem Paket geladen hat, steht er diesen Funktionsaufrufen nicht zur Verfügung. Wir können es zwingen, das Paket zu laden, indem wir zuerst eine der Klassen im Paket wie folgt einleiten:

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

Dies ist jedoch hacky und erfordert wissen, dass der Name einer Klasse, die zum Paket gehört, im Voraus wissen muss.

Die Frage ist also: Gibt es eine Möglichkeit, eine Instanz des Pakets beim Namen zu erhalten, unabhängig davon, ob der Klassenloader etwas getan hat oder nicht? Sind meine Annahmen darüber, wie das Klassenladen/Pakete in dieser Situation zu korrekt zu funktionieren scheinen?

War es hilfreich?

Lösung

Ich gehe davon aus, dass Sie dies brauchen, weil Sie seine Anmerkungen untersuchen müssen. Andernfalls wären Sie nicht daran interessiert, eine Paketreferenz zu erhalten, die nur über Anmerkungen zugänglich ist. Dies führt zu der Annahme, dass Sie dort auch ein Paket-info.java mit einigen Anmerkungen definiert haben.

Wenn Sie überprüfen java.lang.Package Sie werden sehen, dass die getPackageInfo Lädt einfach die Paket-Info-Klasse als gewöhnliche Klasse.

Ich hatte das gleiche Problem und hatte diese Lösung.

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

Andere Tipps

Alternativ können Sie das Klassenstammverzeichnis als Ausgangspunkt verwenden und durch alle *. Class -Dateien und Unterverzeichnisse gehen. Dies würde nur funktionieren, wenn Sie wissen, wo alle Ihre .Class -Dateien im Voraus wohnen.

Die Ursache von all dem ist, dass Java dynamisch klassifiziert hat, sodass die Klassen zur Laufzeit von Standorten geladen werden können, die nicht zur Kompilierungszeit oder sogar zur Startzeit bekannt sind. Daher ist das Konzept eines Pakets nur ein Namespace für geladene Klassen, nicht ein Verzeichnis, mit dem Sie sie nachschlagen können.

Ich befürchte, dass Ihre Annahmen nicht gültig sind. Klassenloader machen ein Paket-Buchhalt, wenn sie Kurse laden.

Sie können eine Wildcard an übergeben ClassLoader.getResources und zwingen Sie es, die Klassen in einem Paket abzuholen, was wiederum die Arbeit erledigt.

Sie können Ihren eigenen Klassenloader machen, der anruft definePackage, Aber das wird Ihnen bei den üblichen Vanilleklassenladern nicht helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top