无法为 tomcat jvm 公开 Java 检测
Cannot expose Java Instrumentation for tomcat jvm
我在 运行 Java 应用程序中使用 tomcat7 实例。我的应用程序需要暴露 Java 检测。这是通过 javaagent 完成的,我在启动时将代理传递给 setenv.bat 脚本中的 JVM。
set JAVA_OPTS=%JAVA_OPTS% -javaagent:"C:\path\to\agent.jar"
在清单文件中我有所需的部分:
Premain-Class: package.name.agent.ExposeInstrumentation
在代理的 premain 方法中 class 将 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() returns 空;
有什么问题?
更新
我做了一些进一步的调试并执行了 premain 并且 s_instrumentation 接收了检测,但是当我稍后在我的代码中调用 getInstrumentation 时 s_instumentation 被设置为 null。这很奇怪,我认为该值在程序的生命周期内仍然有效。
我假设您正在加载 class ExposeInstrumentation
两次。一次通过应用程序 class 加载器,即 child-first (reverse-order),一次通过 Java 代理,其中 class 由系统 class 加载器自动加载。结果,ExposeInstrumentation
class 被加载两次,您从未设置该字段的应用程序访问那个。
您可以通过显式访问系统加载的 class 加载器 class 来解决此问题:
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 Agent project 提供此功能和更多(运行时安装)代理。使用 Byte Buddy,您可以简单地调用 ByteBuddyAgent.getInstrumentation()
.
我在 运行 Java 应用程序中使用 tomcat7 实例。我的应用程序需要暴露 Java 检测。这是通过 javaagent 完成的,我在启动时将代理传递给 setenv.bat 脚本中的 JVM。
set JAVA_OPTS=%JAVA_OPTS% -javaagent:"C:\path\to\agent.jar"
在清单文件中我有所需的部分:
Premain-Class: package.name.agent.ExposeInstrumentation
在代理的 premain 方法中 class 将 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() returns 空;
有什么问题?
更新
我做了一些进一步的调试并执行了 premain 并且 s_instrumentation 接收了检测,但是当我稍后在我的代码中调用 getInstrumentation 时 s_instumentation 被设置为 null。这很奇怪,我认为该值在程序的生命周期内仍然有效。
我假设您正在加载 class ExposeInstrumentation
两次。一次通过应用程序 class 加载器,即 child-first (reverse-order),一次通过 Java 代理,其中 class 由系统 class 加载器自动加载。结果,ExposeInstrumentation
class 被加载两次,您从未设置该字段的应用程序访问那个。
您可以通过显式访问系统加载的 class 加载器 class 来解决此问题:
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 Agent project 提供此功能和更多(运行时安装)代理。使用 Byte Buddy,您可以简单地调用 ByteBuddyAgent.getInstrumentation()
.