C'è un modo per forzare un classloader a caricare un pacchetto anche se nessuna delle sue classi è stata caricata?

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

Domanda

Supponiamo che una base di codice java abbia un pacchetto chiamato " com.example " ;.

In fase di esecuzione, possiamo ottenere questo pacchetto chiamando

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

o anche ottenere un elenco di tutti i pacchetti chiamando

Packages[] ps = Package.getPackages();

Il problema è: se ClassLoader non ha ancora caricato alcuna classe dal pacchetto, non sarà disponibile per queste chiamate di funzione. Possiamo forzarlo a caricare il pacchetto caricando prima una delle classi nel pacchetto, in questo modo:

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

Tuttavia, questo è hacky e richiede di conoscere in anticipo il nome di una classe che appartiene al pacchetto.

Quindi la domanda è: c'è un modo per ottenere un'istanza del pacchetto per nome, indipendentemente dal fatto che ClassLoader abbia fatto qualcosa? I miei presupposti su come i classload / pacchetti sembrano funzionare in questa situazione sono precisi?

È stato utile?

Soluzione

Presumo che tu ne abbia bisogno perché devi ispezionarne le annotazioni. Altrimenti non ti interesserebbe avere un riferimento al pacchetto in cui solo le operazioni riguardano l'accesso alle annotazioni. Questo porta al presupposto che tu abbia anche un pacchetto-info.java definito lì con alcune annotazioni.

Se selezioni java.lang.Package vedrai che getPackageInfo carica semplicemente la classe di informazioni sul pacchetto come una normale classe.

Ho avuto lo stesso problema e ho trovato questa soluzione.

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

Altri suggerimenti

In alternativa è possibile utilizzare la directory principale della classe come punto di partenza e scorrere tutti i file * .class e le sottodirectory. Funzionerebbe solo se sai prima dove risiederanno tutti i tuoi file .class.

La causa di tutto ciò è che Java ha un caricamento dinamico delle classi, quindi le classi possono essere caricate in fase di esecuzione da posizioni non note al momento della compilazione o anche al momento dell'avvio. Pertanto, il concetto di pacchetto è solo uno spazio dei nomi per le classi caricate, non una directory che è possibile utilizzare per cercarle.

Temo che i tuoi presupposti non siano validi. I classloader tengono la contabilità dei pacchetti mentre caricano le classi.

Puoi passare un carattere jolly a ClassLoader.getResources e forzarlo a raccogliere le classi in un pacchetto, che a sua volta farà il lavoro.

Puoi creare il tuo ClassLoader che chiama definePackage , ma ciò non ti aiuterà con i soliti classloader vanilla in uso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top