2015-07-02 45 views
3

我想通過-javaagent:my-agent.jar標誌添加到我的應用程序中的javaagent jar中的servlet-api中訪問類。我的應用程序在Tomcat上運行。問題是我得到一個ClassNotFoundException,因爲代理jar由一個沒有訪問servlet-api類的類加載器加載。在javaagent中訪問servlet-api

更具體地說,我想包括ServletContainerInitializer在我javaagent

public class MyInitializer implements ServletContainerInitializer { 
    @Override 
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { 
     System.out.println(ctx); 
    } 
} 

META-INF /服務/ javax.servlet.ServletContainerInitializer

org.example.MyInitializer 

結果是一個ClassNotFoundException因爲ServletContainerInitializer不能被發現。

有沒有辦法訪問javaagent中的servlet-api?或者更一般地說,是否可以訪問任何通過ApplicationClassLoader加載的類,就像Spring框架中的類一樣?

+0

有你解決了嗎? – nadavy

+1

不,還沒有:-( – Felix

+0

@Felix從javaagent jar中加載動態servlet有什麼好運? – Vikdor

回答

1

如果你的代理人有premain方法爲署名像

public static void premain(String agentArgs, Instrumentation inst) 

你拿到手的Instrumentation對象,它提供的方法getAllLoadedClasses()getInitiatedClasses(ClassLoader)上。現在每次搜索這些數組並且僅通過反射使用Class實例會很尷尬。但是,您可以使用這些方法找到所需的API類,確定其運行時間ClassLoader並創建一個新的ClassLoader,將其用作解決方案父項並指向需要它們的代理類。

+0

這個「指向我的代理類」是怎麼樣的?另一個問題是MyInitializer類是由Application Server加載的在啓動時,所以更難以混淆類加載器 – Felix

+1

例如,將所有與'MyInitializer'相關的類放入一個jar文件中,並使用指向jar文件的'file:'URL創建一個'URLClassLoader' 。可能你的代理不得不推遲初始化,直到servlet容器完全初始化爲止。我不太瞭解你的用例,告訴你需要等待什麼條件,但是請注意,你可以使用'addTransformer'來註冊一個變量它只是簡單地返回'null'而不進行實際的轉換。由於每個加載的類都會調用該轉換器,因此您將瞭解何時您想要的類會得到由tomcat加載。 – Holger

0

對我來說有效的是我在ClassPool.insertClassPath中添加了servlet-api.jar文件。這解決了這個問題。

ClassPool $pool = ClassPool.getDefault(); 
      try { 
       $pool.insertClassPath("/apache-tomcat-7.0.50/lib/servlet-api.jar"); 
      } catch (NotFoundException e) { 
       throw new RuntimeException(e); 
      } 
    return $pool; 

https://github.com/presci/MyAgent.git