【问题标题】:Cannot expose Java Instrumentation for tomcat jvm无法为 tomcat jvm 公开 Java Instrumentation
【发布时间】:2016-07-09 10:56:43
【问题描述】:

我正在使用 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_instumentation 设置为 null。这很奇怪,我认为该值在程序的生命周期内仍然有效。

【问题讨论】:

  • 你的premain方法真的被调用了吗?
  • premain 已执行,但我没有得到任何工具

标签: java tomcat instrumentation javaagents


【解决方案1】:

我假设您正在加载类ExposeInstrumentation 两次。一次由应用程序类加载器child-first (reverse-order) 一次通过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 Agent project。使用 Byte Buddy,您只需拨打ByteBuddyAgent.getInstrumentation()

【讨论】:

  • 还有...有没有办法阻止应用程序类加载器加载 ExposeInstrumentation,这样它就不会被加载两次?
  • 应该是 loadClass 而不是 findClass。您可以通过将ExposeInstrumentation 类放入它自己的模块中并为Web 应用程序声明一个 provided 范围依赖项来防止重复加载。只要附加了代理,这将起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多