2009-11-29 14 views
15

Diciamo che un codice java ha un pacchetto chiamato "com.example".C'è un modo per forzare un classloader a caricare un pacchetto anche se nessuna delle sue classi è stata caricata?

In fase di esecuzione, possiamo ottenere questo pacchetto chiamando

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

o persino ottenere un elenco di tutti i pacchetti chiamando

Packages[] ps = Package.getPackages(); 

Il problema è - se il ClassLoader non ha ancora caricato alcun classe dal pacchetto, non sarà disponibile per queste chiamate di funzione. Siamo in grado di forzare per caricare il pacchetto con la forza di carico una delle classi del primo 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 la conoscenza prima del tempo il nome di una classe che appartiene a il pacchetto.

Quindi la domanda è: esiste un modo per ottenere un'istanza di Pacchetto per nome, indipendentemente dal fatto che ClassLoader abbia o meno eseguito qualcosa? Le mie supposizioni su come il classloading/pacchetti sembrano funzionare in questa situazione accurata?

+0

Attenzione alle https://stackoverflow.com/questions/3455267/why-does-class-getpackage-return-the-same-package-for-classes-from-different-pac – Vadzim

risposta

11

In alternativa, è possibile utilizzare la directory radice classe come punto di partenza e percorrere tutti i file * .class e le sottodirectory. Questo funzionerebbe solo se sapessi dove risiedono in anticipo 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 runtime da posizioni non note al momento della compilazione o anche all'avvio. Quindi il concetto di un pacchetto è solo uno spazio dei nomi per le classi caricate, non una directory che puoi usare per cercarle.

5

Ho paura che le tue supposizioni non siano valide. I classloader eseguono la gestione contabile dei pacchetti man mano che caricano le classi.

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

È possibile creare il proprio ClassLoader che chiama definePackage, ma ciò non è di aiuto con i soliti classloader di vanilla in uso.

5

Presumo che sia necessario perché è necessario ispezionare le sue annotazioni. Altrimenti non saresti interessato ad avere un riferimento al pacchetto che riguarda solo le operazioni che riguardano l'accesso alle annotazioni. Questo porta a pensare che tu abbia anche un pacchetto-info.java definito lì con alcune annotazioni.

Se si seleziona java.lang.Package vedrete che il getPackageInfo carica semplicemente la classe info pacchetto come una classe ordinaria.

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