Problemi con Classloader - Come determinare quali versioni di libreria (file jar) vengono caricate

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

  •  02-07-2019
  •  | 
  •  

Domanda

Ho appena risolto un altro * I-sebbene-stavo usando-questa-versione-di-una-libreria-ma-apparentemente-il-mio-server-app-ha-già-caricato-un-vecchio- versione-di-questa-libreria- * problema (sospiro).

Qualcuno conosce un buon modo per verificare (o monitorare) se l'applicazione ha accesso a tutti i file jar appropriati o alle versioni di classe caricate?

Grazie in anticipo!

[P.S. Un ottimo motivo per iniziare a utilizzare architettura del modulo OSGi a mio avviso!]

Aggiornamento : Anche questo articolo ha aiutato ! Mi ha fornito informazioni sulle classi caricate dal classloader di JBoss scrivendole in un file di registro.

È stato utile?

Soluzione

Se ti capita di usare JBoss, c'è un MBean (il repository del caricatore di classi iirc) dove puoi chiedere a tutti i caricatori di classi che hanno caricato una determinata classe.

Se tutto il resto fallisce, c'è sempre 'java -verbose: class' che stamperà la posizione del vaso per ogni file di classe che viene caricato.

Altri suggerimenti

Se hai informazioni sulla versione appropriata in un manifest jar, ci sono metodi per recuperare e testare la versione. Non è necessario leggere manualmente il manifest.

java.lang.Package .getImplementationVersion () e getSpecificationVersion () e isCompatibleWith () sembrano che farebbero quello che stai cercando.

Puoi ottenere il pacchetto con this.getClass (). getPackage () tra gli altri modi.

Il javadoc per java.lang.Package non fornisce i nomi degli attributi manifest specifici per questi attributi. Una rapida ricerca su Google l'ha trovata su http: // java. sun.com/docs/books/tutorial/deployment/jar/packageman.html

Nell'attuale versione di Java, il versioning delle librerie è un termine piuttosto lanoso che si basa sul fatto che JAR sia impacchettato correttamente con un manifest utile. Anche in questo caso, è molto lavoro per l'applicazione in esecuzione raccogliere queste informazioni insieme in modo utile. Il runtime JVm non ti dà alcun aiuto.

Penso che la tua scommessa migliore sia far rispettare questo in fase di costruzione, usando strumenti di gestione delle dipendenze come Ivy o Maven per recuperare le versioni corrette di tutto.

È interessante notare che Java 7 includerà probabilmente un framework di versioning del modulo adatto proprio a questo genere di cose. Non è quello che ti aiuta in questo momento,

Non credo ci sia un buon modo per verificarlo. E non sono sicuro che tu voglia farlo. Quello che devi fare è acquisire familiarità con l'architettura di caricamento della classe del tuo server di app e capire come funziona.

Una spiegazione semplificata di come funziona è: un bean o un'app Web cercheranno prima una classe o una risorsa nelle librerie dichiarate nel proprio modulo (ejb-jar o war). se la classe non viene trovata lì, il programma di caricamento classi inoltra la richiesta al programma di caricamento classe padre che è una dipendenza dichiarata (di solito un ejb) o il programma di caricamento classe applicazione responsabile del caricamento delle librerie e delle risorse dichiarate nel pacchetto ear . Se la classe o la risorsa non viene ancora trovata, la richiesta viene inoltrata al server dell'app che cercherà nel proprio percorso di classe.

Detto questo, dovresti ricordare che un modulo Java EE (web-app, ejb) caricherà sempre le classi da un jar che si trova nell'ambito più vicino. Ad esempio, se si pacchetto log4j v1 nel file di guerra, log4j v2 a livello di orecchio e si inserisce log4j v3 nel percorso di classe del proprio server delle app, il modulo utilizzerà il jar nel proprio modulo. portalo via e userà quello a livello dell'orecchio. eliminalo e userà quello nel percorso di classe del server delle app. Le cose diventano più complicate quando si hanno dipendenze complesse tra i moduli.

La cosa migliore è mettere le librerie globali dell'applicazione a livello dell'orecchio.

Deve esserci un modo migliore del modo in cui lo faccio, ma tendo a farlo in un modo molto manuale.

  1. Ogni Jar deve avere il suo numero di versione nel nome del file (se non cambia il suo nome).
  2. ogni applicazione ha il suo percorso di classe.
  3. Ci deve essere un motivo per iniziare a usare un Jar aggiornato (nuova versione). Non cambiare solo perché è disponibile, cambia perché ti offre le funzionalità di cui hai bisogno.
  4. Ogni versione deve includere tutti i barattoli necessari.
  5. Conservo una classe Version che conosce l'elenco di Jars di cui ha bisogno (questo è codificato nel file sorgente) e può essere verificato in fase di esecuzione rispetto all'elenco di Jars nel percorso di classe.

Come ho detto, è manuale, ma funziona.

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