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

7
为了支持更好的分析数据,我想让我的JVMTI代理程序启用几个JVM标志。这个代理程序是指Honest-Profiler,它只能在启动时加载。
我想启用以下标志:-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints 根据这里记录的问题,如果未开启这些标志,则会导致偏差分析。最好的方法是不仅警告用户而且直接启用这些标志。

2
如果您找不到合法的解决方案,@apangin提供了一种可怕的方法:https://github.com/odnoklassniki/one-elf/blob/master/test/one/jvm/HotspotFlags.java 它可以找到已加载的libjvm.so的地址,并从.so地址+ .symtab常量偏移量计算标志地址(但它并不总是有效,取决于VM代码中具体的标志使用情况) - qwwdfsad
3个回答

11

关于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上有一个丑陋的技巧可以实现此操作。

  1. 读取/proc/self/maps以查找libjvm.so的基地址。
  2. 使用ELF格式阅读器发现动态库中所需符号的偏移量。
  3. 直接写入该符号的地址。

这里是一个示例代码来实现此技巧。


我已经通过Helfy(也使用Hotspot SA)对其进行了管理。当我准备好时,我会用示例代码展示它。 - Serkan Özal
1
请看这里 https://github.com/serkan-ozal/jvm-playground/blob/master/src/main/java/tr/com/serkanozal/jvm/playground/ChangeImmutableVmFlagDemo.java - Serkan Özal
@SerkanÖzal 很酷!没想到 Helfy 可以用于这个。你介意把这个例子添加到 Github 上的 Helfy 仓库中吗? - apangin
当然,@apangin,如果您想要的话,我可以发送一个PR :) - Serkan Özal
@SerkanÖzal 当然,请继续创建PR。谢谢! - apangin

1

好的,这并不是一个精确的答案,而是在某个方向上的推动....

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


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接