JVMTI 代理如何在启动时设置 JVM 标志?

How can JVMTI agent set a JVM flag on startup?

为了支持更好的分析数据,我希望我的 JVMTI 代理启用几个 JVM 标志。 有问题的代理是 Honest-Profiler,它只能在启动时加载。

我想启用标志:-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints

根据记录的问题 here 如果标志未打开,我们会得到有偏见的配置文件。最好不要警告用户并启用该标志。

好吧,这不是一个精确的答案,但更多的是在某个方向上的推动....

services/writeableFlags.hpp中有设置虚拟机标志的静态方法。成功将取决于这些标志是否实际上是可变的,但它是开始探索的好地方。我没有尝试从 JVMTI 代理调用这些方法,但理论上它应该可以工作。

有几个 JVM 标志可以在运行时使用 com.sun.management.HotSpotDiagnosticMXBean.setVMOption 编写。

(有关列表,请参阅 http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/b92c45f2bc75/src/share/vm/runtime/globals.hpp 并搜索 manageable)。

不幸的是,对于您的用例,选项 UnlockDiagnosticVMOptions 不可写。

至于DebugNonSafepoints你甚至不需要设置这个标志。看看debugInfoRec.cpp:

static inline bool compute_recording_non_safepoints() {
  if (JvmtiExport::should_post_compiled_method_load()
      && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
    // The default value of this flag is taken to be true,
    // if JVMTI is looking at nmethod codes.
    // We anticipate that JVMTI may wish to participate in profiling.
    return true;
  }

  // If the flag is set manually, use it, whether true or false.
  // Otherwise, if JVMTI is not in the picture, use the default setting.
  // (This is true in debug, just for the exercise, false in product mode.)
  return DebugNonSafepoints;
}

如果未设置标志,则在启用 JVMTI CompiledMethodLoad 通知时仍会记录调试信息。您只需要请求 can_generate_compiled_method_load_events 功能并打开 JVMTI_EVENT_COMPILED_METHOD_LOAD 通知。

这正是我在 async-profiler 项目中处理它的方式。


没有安全的方法可以在 运行 时间内更改难以管理的 JVM 标志。然而,在 Linux.

上有一个丑陋的 hack 可以做到这一点
  1. 读取/proc/self/maps找到libjvm.so的基地址。
  2. 使用ELF format reader在动态库中发现所需符号的偏移量。
  3. 直接写入这个符号的地址。

这是这个技巧的a sample code