2013-08-05 29 views
2

我已經創建了一個Java代理jar文件(它可以在命令行上完美工作)。 接下來,我想將此代理附加到j2ee服務器中正在運行的JVM。 所以我使用的代碼:如何在代碼中動態添加Java代理程序後卸載Java代理程序? Java儀器

public static void loadAgent() { 

    System.out.println("dynamically loading javaagent"); 
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); 
    int p = nameOfRunningVM.indexOf('@'); 
    String pid = nameOfRunningVM.substring(0, p); 

    try { 
     VirtualMachine vm = VirtualMachine.attach(pid); 
     String jarFilePath = vm.getSystemProperties().getProperty("java.home")+File.separator+"lib"+File.separator+"test-agent-7.jar";    
     vm.loadAgent(jarFilePath, ""); 
     vm.detach(); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

編輯:這是現在的工作,我能看到,變壓器被調用。 我也可以刪除變壓器,並能夠調試變壓器。

我的問題是:

  • 我如何卸載這個Java代理罐子一旦完成了嗎?
  • 是關閉/重新啓動JVM的唯一方法嗎?
  • 如果jar留在內存中,是否有任何影響?
+0

你解決了你的問題@Tal? –

+0

不幸的是...代理罐保持加載.. – Tal

回答

2

那麼,有幾件事情要考慮:

如果加載代理,你加載類。只要相關的類加載器位於Java VM的內存中,相關的類將保持加載狀態。我認爲你不能輕易地預防/規避。但是,這應該只是一個小的內存開銷,你可以通過加載一個代理來實現。

的研究的位指示該代理將被SystemClassLoader被加載,所以卸載這些類將是不可能的。

開始代理VM啓動

後的實現可以提供一種機制,在VM啓動之後某一時刻啓動代理 。關於如何啓動 的細節是特定於實現的,但通常應用程序已經啓動並且其主要方法已被調用。在 實現支持代理商啓動VM具有後 開始適用以下情況: 代理JAR的清單必須包含屬性代理級。此屬性的值是代理 類的名稱。 代理類必須實現一個公共靜態代理主方法。 系統類加載器(ClassLoader.getSystemClassLoader)必須支持將代理JAR文件添加到系統類路徑的機制。 Link to source

然而,您可以影響什麼,代理正在做什麼。

你想關閉該代理?提供關閉方法。

如果你想阻止來自外部的代理,這個代理可以提供一個JMXBean其關閉代理下來。

該方法可以從Instrumentation界面中刪除變換器,或者停止代理在Java VM內部執行的任何操作(釋放引用/資源,以便對象被垃圾收集,像這樣)。

沒有關於你想達到什麼的更具體,很難給出更好的答案。