我正在尝试通过-javaagent:my-agent.jar标志添加到我的应用程序的javaagent jar中的servlet-api访问类。我的应用程序在Tomcat上运行。问题是我收到ClassNotFoundException,因为代理jar由无法访问servlet-api类的类加载器加载。
更具体地说,我想在我的javaagent中包含一个ServletContainerInitializer
public class MyInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
System.out.println(ctx);
}
}
META-INF / services / javax.servlet.ServletContainerInitializer
org.example.MyInitializer
结果是ClassNotFoundException,因为找不到ServletContainerInitializer。
有什么方法可以在javaagent中访问servlet-api?或更笼统地说,是否可以访问通过ApplicationClassLoader加载的任何类,例如spring框架中的类?
最佳答案
如果您的代理人有一个带有签名的premain
方法,例如
public static void premain(String agentArgs, Instrumentation inst)
您将获得一个
Instrumentation
对象,该对象提供了 getAllLoadedClasses()
和 getInitiatedClasses(ClassLoader)
方法。现在,每次搜索这些数组并仅通过反射使用Class
实例将很麻烦。但是您可以使用这些方法找到所需的API类,确定其运行时ClassLoader
并使用它作为解析父级并指向需要它们的代理类,以创建新的ClassLoader
。