无法公开tomcat jvm的Java检测

无法公开tomcat jvm的Java检测,java,tomcat,instrumentation,javaagents,Java,Tomcat,Instrumentation,Javaagents,我正在使用tomcat7实例来运行Java应用程序。我的应用程序需要公开Java工具。这是通过javaagent完成的,我在启动时通过setenv.bat脚本将代理传递给JVM set JAVA_OPTS=%JAVA_OPTS% -javaagent:"C:\path\to\agent.jar" 在清单文件中,我有必要的部分: Premain-Class: package.name.agent.ExposeInstrumentation 在代理类的premain方法中,将JVM提供的工具分配

我正在使用tomcat7实例来运行Java应用程序。我的应用程序需要公开Java工具。这是通过javaagent完成的,我在启动时通过setenv.bat脚本将代理传递给JVM

set JAVA_OPTS=%JAVA_OPTS% -javaagent:"C:\path\to\agent.jar"
在清单文件中,我有必要的部分:

Premain-Class: package.name.agent.ExposeInstrumentation
在代理类的premain方法中,将JVM提供的工具分配给通过静态方法访问的静态变量

public final class ExposeInstrumentation {
private static Instrumentation s_instrumentation;
public static void premain(String arguments, Instrumentation instrumentation) {
    s_instrumentation = instrumentation;
}

public static Instrumentation getInstrumentation() {
    return s_instrumentation;
}
}
但在我的代码中,当我这样做时:

Instrumentation instrumentation = ExposeInstrumentation.getInstrumentation();
getInstrumentation()返回null

有什么问题

更新


我做了一些进一步的调试,并执行了premain,s_instrumentation收到了该指令,但是当我稍后在代码中调用getInstrumentation时,s_instrumentation被设置为null。这很奇怪,我认为该值在程序的生命周期内仍然有效。

我假设您正在加载类
ExposeInstrumentation
两次。一次由应用程序类加载器加载,一次通过Java代理,系统类加载器自动加载该类。因此,
ExposeInstrumentation
类在您从未设置字段的应用程序访问该类时被加载两次

您可以通过显式访问系统类加载器加载的类来解决此问题:

class ExposeInstrumentation {

  // public to assure accessability
  public static Instrumentation s_instrumentation;

  public static void premain(String arguments, Instrumentation inst) {
    s_instrumentation = inst;
  }

  public static Instrumentation getInstrumentation() {
    try {
      return (Instrumentation) ClassLoader.getSystemClassLoader()
          .loadClass(ExposeInstrumentation.class.getName())
          .getDeclaredField("s_instrumentation")
          .get(null);
    } catch(Exception e) {
      return null;
    }
  }
}

您还可以查看提供此功能的以及更多(运行时安装)代理的。使用Byte Buddy,您只需调用
ByteBuddyAgent.getInstrumentation()

您的
premain
方法是否实际被调用?premain被执行,但我没有得到任何指令……是否有方法阻止应用程序类加载器加载ExposeInstrumentation,使其不会被加载两次?应该是
loadClass
而不是
findClass
。通过将ExposeInstrumentation类放入其自己的模块中,并为web应用程序声明提供的作用域依赖项,可以防止重复加载。只要附加了代理,这就可以工作。