我正在尝试通过-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

09-16 00:18