2013-09-25 6 views
9

Quando l'imballaggio di un file jar con l'agente Java personalizzato, è possibile aggiungere le seguenti proprietà:Differenza tra ridefinire e ritrasformare in javaagent

  • Can-Redefine-Classes
  • Can-Retransform-Classes

Qual è la differenza tra coloro Due?

Se la ridefinizione avviene prima che la classe venga caricata e dopo la retransformazione, allora quando avviene esattamente la ritrasformazione?

risposta

4

La ridefinizione significa che in un punto arbitrario un agente invocherà la strumentazione. redefineClasses per modificare la definizione effettiva delle classi esistenti (e già caricate). L'agente fornirà il bytecode per la nuova definizione.

La ritrasformazione si riferisce al processo di trasformazione del file di classe che viene normalmente applicato in fase di caricamento della classe. Gli agenti possono registrare ClassFileTransformers chiamati uno dopo l'altro per applicare le trasformazioni al codice byte prima che la classe venga inizializzata. Pertanto, la ritrasformazione fa riferimento alla capacità della JVM di ripetere questo processo per le classi già caricate. In questo caso un agente può richiamare Instrumentation.retransformClasses specificando le classi da ritrasmettere ma non il bytecode. Invece la JVM chiamerà tutti i ClassFileTransformers capaci di ritrasmissione registrati che forniscono il bytecode effettivo (o il risultato del precedente trasformatore per un trasformatore incatenato).

3

Sembrano quasi ridondanti nella funzionalità che ci offrono. La differenza principale sembra essere che quando abbiamo ridefinire una classe, forniamo un byte[] con la nuova definizione fuori dal blu, mentre quando noi si ritrasmettono, otteniamo uno byte[] contenente la definizione corrente tramite la stessa API, e noi restituire un byte[] modificato.

Pertanto, per ridefinire, è necessario conoscere meglio la classe. Considerare il caso d'uso dell'iniezione di dichiarazioni di tracciamento di profilazione. Con ritrasmette puoi farlo più direttamente: basta guardare il bytecode dato, modificarlo e restituirlo. Ma se siamo passati alla route ridefinire, avremmo bisogno di recuperare l'originale byte[] da qualche parte (come getResourceAsStream()).

Un'altra differenza apparente riguarda il modo in cui interagiamo con altri trasformatori di classe; chi va per primo Le trasformazioni vengono applicate alla classe originale o ridefinita, quindi diverse trasformazioni possono essere additive, ad esempio.

Storicamente, se guardiamo le Dal commenti nel API documentation, o, a pagina 238 del this book (Friesen 2007 partire Java SE 6 Platform), notiamo che ridefinizione funzionalità sono state introdotte in Java 5, e di ritrasformazione in Java 6. La mia ipotesi è che la ritrasformazione sia stata introdotta come funzionalità più generale, ma la ridefinizione doveva essere mantenuta per compatibilità con le versioni precedenti.

Citando la frase chiave su ritrasformazione metodi dal libro legati sopra:

agenti utilizzano questi metodi per ritrasformare classi precedentemente caricate senza la necessità di accedere ai propri file di classe.


La seconda parte della domanda:

Se ridefinizione accade prima classe viene caricata e ritrasformazione dopo, poi, quando fa esattamente ritrasformazione accada?

No, la ridefinizione avviene dopo che la classe è stata caricata, oltre alla ritrasformazione. Accadono quando si chiamano i metodi redefineClasses(..) edell'istanza, rispettivamente.

Ecco una domanda per gli esperti di passaggio: c'è qualcosa che si può fare da ridefinendo classi, che non si può fare da ritrasformandosi loro? La mia ipotesi è che la risposta sia "nulla".