Sto utilizzando l'API di collegamento per caricare un agente JVMTI in fase di runtime. Vorrei scaricare l'agente JVMTI quando il mio programma è terminato senza terminare la JVM in cui è caricato l'agente. Secondo this documentation non c'è modo di farlo dall'API attach. Esistono altri modi per forzare un agente a scaricare se stesso tramite un'API Java o dall'agente JVMTI?Scaricamento di un agente JVMTI in fase di runtime?
risposta
JVMTI spec says lo scaricamento (senza terminazione JVM) è possibile, ma dipende dalla piattaforma e dall'ambito della specifica.
È necessario caricare JVMTI agente programmaticamente:
// attach to target VM
VirtualMachine vm = VirtualMachine.attach("2177");
// get system properties in target VM
Properties props = vm.getSystemProperties();
// construct path to management agent
String home = props.getProperty("java.home");
String agent = home + File.separator + "lib" + File.separator
+ "your-agent-example.jar";
// load agent into target VM
vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");
// detach
vm.detach();
vedere doc here
Dopo di che è necessario utilizzare un classLoad diverso da quello di default:
È necessario impostare la proprietà di sistema "java .system.class.loader "per essere il nome del caricatore di classi personalizzato per la JVM di destinazione.
vedere doc here
"caricatori di classi predefinite in Java controlla sempre se una classe è già stato caricato prima di caricarla. a ricaricare la classe non è quindi possibile utilizzare caricatori incorporate classe di Java. Per ricaricare una classe si dovrà implementare la propria sottoclasse ClassLoader. "
Nel tuo caso devi implementare un ClassLoader che ha ClassLoader.getSystemClassLoader() ha genitore.
"Anche con una sottoclasse personalizzata di ClassLoader si dispone di una sfida. Ogni classe caricata deve essere collegata. Questo viene fatto usando il metodo ClassLoader.resolve(). Questo metodo è definitiva, e quindi non può essere ignorata nella sottoclasse ClassLoader. Il metodo resolve() non consente a nessuna determinata istanza ClassLoader di collegare due volte la stessa classe. Pertanto, ogni volta che si desidera ricaricare una classe è necessario utilizzare una nuova istanza della sottoclasse ClassLoader. Questo non è impossibile, ma necessario sapere quando si progetta di ricaricare la lezione. "
vedere Dynamic Class Reloading
Questo non aiuta gli agenti JVMTI che sono codice nativo. Il distacco dalla JVM non causa la rimozione dell'agent JVMTI. – Jared
Non lo dico. L'esempio di codice è qui solo per mostrare come caricare l'agente. Unloading agent dalla JVM è lo stesso problema che si verificano durante lo scaricamento delle classi. L'unica soluzione è usare il proprio caricatore di classe. – EricParis16
Se si esamina il documento attach, viene chiaramente indicato che loadAgent viene utilizzato per caricare gli agenti scritti in Java mentre loadAgentLibrary e loadAgentPath vengono utilizzati per caricare gli agenti JVMTI che sono codice nativo. Poiché gli agenti JVMTI sono codice nativo e non classi Java, la tua discussione sui programmi di caricamento classi non si applica. Vedi http://download.oracle.com/javase/6/docs/jdk/api/attach/spec/index.html – Jared
Questo non significa essere una risposta adeguata, ma solo un suggerimento. Ho avuto un problema simile con JNI (volevo scaricare un modulo). La soluzione migliore che ho trovato è semplice: generare una nuova istanza JVM eseguendo il lavoro con il modulo, attendere che si concluda, e quindi quando viene terminato, il modulo è ovviamente scaricato. Scommetto che finirai per farlo, dopo aver lottato per un po '. Vi suggerisco di saltare la fase di "lotta": P – gd1