2015-05-07 5 views
7

Sto provando a tenere traccia delle allocazioni di tutti gli oggetti in JVM.Aggiunta di invokestatic a java/lang/Object. <init> tramite l'agente JVM TI causa l'arresto anomalo di JVM con segfault

Nei vari documenti su profiler di allocazione è stato detto che il modo più semplice per farlo è questo: aggiungere invokestatic Tracker.trackAllocation()V istruzione per java/lang/Object.<init> (normalmente costituito da un unico return istruzioni, aggiungiamo invokestatic prima di esso, quindi è 2 istruzioni ora).

(So che questo approccio è lento e non tiene traccia delle allocazioni di array, ma volevo iniziare con la soluzione più semplice, inoltre non ho passato il riferimento all'oggetto assegnato al tracker, ma questo verrà aggiunto in seguito.)

Il file di classe è dotato di agente JVM TI in hook onClassLoaded.

Tuttavia, dopo aver aggiunto invokestatic, l'istruzione JVM si arresta in modo anomalo con segfault. L'oggetto tracker viene aggiunto al bootloader del bootstrap, quindi dovrebbe essere visibile in qualsiasi momento. Ho provato ad aggiungere nop invece di invokestatic e JVM funziona correttamente con la classe Object modificata. Quindi il problema riguarda specificamente l'invocazione di alcuni metodi statici.

Ho anche provato a utilizzare le applicazioni dello strumento (non parte della base) e ha funzionato correttamente: è stato chiamato il tracker e non si sono verificati arresti anomali. Ho anche provato a ridefinire l'oggetto in 2 punti: quando è stato caricato inizialmente (prima classe caricata), o dopo evento vmInit (quando tutte le classi base sono caricate e le restrizioni su jni vengono rimosse).

C'è qualcosa che mi manca nello strumenting java.lang.Object?

Codice per l'agente è qui: https://gist.github.com/Korobochka/3bf2f906f6ab85b22dec (controllo degli errori è spogliato, il codice per cambiare le classi, inoltre, non incluso, ma funziona abbastanza bene per le altre classi)

+0

Mostraci il codice – apangin

+0

@apangin Ho aggiunto l'essenza con il codice agente in fondo alla domanda. Questa è la versione in cui Object viene modificato dopo vmInit. – Korobochka

+1

Penso che il problema sia che la classe 'Tracker' è un oggetto stesso, che deve essere istanziato prima che venga creato un oggetto, ma ciò richiederebbe il caricamento della classe prima ... e così via. Hai bisogno di rompere quel ciclo in qualche modo. – biziclop

risposta

5

Sembra che il problema è nel chiamare System.out.println da LeakAgentInterface. Innanzitutto, System.out potrebbe non essere ancora inizializzato. In secondo luogo, println potrebbe allocare gli oggetti stessi.

+1

E questo include il 'String' che verrà stampato che è anche un oggetto; anche le costanti in fase di compilazione 'String's devono essere allocate in fase di esecuzione quando vengono utilizzate la prima volta ... – Holger

+0

Appena verificato, questo è davvero il caso. Grazie mille!Ho sprecato un paio d'ore su questo e l'errore è stato molto semplice e stupido = (ma stavo cercando il bug solo nel codice C++. – Korobochka