2010-01-25 10 views
8

Qualcuno su cui lavoro ha notato (in stacktrace) che durante l'esecuzione di jvm con -javaagent: spring-instrumentation.jar le mie classi annotate JAXB hanno strani nuovi metodi in esse che non abbiamo scritto: ad es. SomeJaxbAnnotatedClass $ JaxbAccessorM_getFields_setFields_java_util_Set.getJAXB utilizza la strumentazione bytecode?

Ciò significa che jaxb utilizza la strumentazione bytecode quando è disponibile? Dove posso leggere di più su questa funzionalità?

Grazie, Yuval

risposta

12

solo un'aggiunta al post di skaffman:

Quello che si vede (SomeJaxbAnnotatedClass $ JaxbAccessor ...) è una classe interna, che viene generata dinamicamente dal implementazione di riferimento JAXB. Per prevenire il sovraccarico di riflessione in fase di esecuzione, il bytecode per le implementazioni concrete della classe com.sun.xml.bind.v2.runtime.reflect.Accessor viene generato e inserito nel classloader corrente richiamando ClassLoader.defineClass (String, byte [], int, int), dopo aver utilizzato la reflection per aggirare il modificatore di accesso protetto del metodo defineClass.

Quindi, l'implementazione di riferimento JAXB non è lo strumento bytecode nel senso che modifica le classi esistenti, ma genera nuove classi per prestazioni di runtime ottimizzate.

+0

(+1) bella aggiunta. – skaffman

+0

Grazie per aver chiarito questo concetto, avrei dovuto confondere le classi interne con metodi aggiuntivi e immaginato che la strumentazione a molla potesse avere qualcosa a che fare con questo. Quello che descrivi ha molto più senso :) –

1

scorso ho controllato, JAXB utilizza la riflessione per generare classi sulla base del XML che fornisci (anche se non l'ho usato in un certo tempo, in modo che possano hanno cambiato la loro metodologia).

So che JiBX, d'altra parte, utilizza BCEL per eseguire la strumentazione bytecode. Ecco un articolo a riguardo: http://www.ibm.com/developerworks/java/library/j-cwt09065/.

+0

Io so tutto su JIBX l'ho usato e ho sofferto ogni minuto di dover eseguire la compilazione dei post, ero semplicemente sorpreso di vedere JAXB fare qualcosa che somigliava al bytecode ma suppongo di aver sbagliato ... –

8

Quando si avvia JaxbContext, esegue una grande quantità di operazioni di riflessione per pre-memorizzare nella cache tutte le cose di cui avrà bisogno in seguito. Questo è fatto per motivi di prestazioni. Non sono sicuro di ciò che fa esattamente, ma mi aspetto che esegua una sorta di logica di generazione di classi runtime, dal momento che sarà più veloce in fase di esecuzione rispetto alla riflessione grezza.

È interessante notare che è possibile disattivare questo comportamento impostando una proprietà di sistema non documentata, che migliora l'avvio del contesto, a scapito delle prestazioni di runtime.

modifica: Devo sottolineare che questo è ciò che l'implementazione di riferimento di Sun JAXB fa sotto le copertine, non fa parte delle specifiche JAXB. Altre implementazioni sono libere di fare tutto ciò che scelgono.

+1

+1 per menzionare che potrebbero esserci implementazioni differenti che sono implementate in modo diverso! –

0

Come menzionato da skaffman è possibile disattivare la generazione di tutte quelle classi interne impostando la proprietà di sistema: com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.fastBoot = true

Naturalmente non è documentato, ma non è cambiato da anni.