比 JVMTI GetTag 更快的获取对象标签的方法

Faster alternative to get tags for objects than JVMTI GetTag

在使用异步分析器和 gperftools 进行分析时,我注意到 jvmti->GetTag 在我的代理结果中出现了很多。当我检查它是如何实现的时,我在 jvmitTagMap.cpp 的源代码中发现了以下内容:

jlong JvmtiTagMap::get_tag(jobject object) {
  MutexLocker ml(lock());

  // resolve the object
  oop o = JNIHandles::resolve_non_null(object);

  // for Classes get the tag from the klassOop
  return tag_for(this, klassOop_if_java_lang_Class(o));
}
  1. 虽然我的测试只有一个真正处于负载下的线程,但一旦我添加更多线程并大量使用 GetTag,这似乎会更小。

我想使用标签为某些对象分配一个 id 并在我的 jvmti 代理中使用它。有什么更快的方法可以做到这一点吗?弄乱对象头显然不是一种选择(据我所知)。

注意:大多数事情应该在 C 端完成,因为我不希望我的 Java 代理以任何方式干扰应用程序。我所说的干扰甚至是指改变某些中心对象的内部状态/类(例如 java.lang.StringCoding),或导致某些 类 被加载等

GetTag 已经在当前的 JVMTI 代理中大量使用,所以我正在寻找一种更快的方法来获取标签或实现我自己的机制,同时留在 C 端。

当您使用来自 C 的 Java 对象时,您基本上会受到 JNI 和 JVMTI 函数的限制。他们确实有不可避免的开销。

恐怕没有其他合法方法可以从本地代理访问 Java 对象。特别是,处理 naked oop 是非法的——这只是一个原始指针,它可能随时失效,因为对象可以移动。

然而,JVM 可以使用 oops,甚至可以使用对象地址作为 JvmtiTagMap 中的键,只要它在移动对象时更新相应的 oops。 HotSpot JVM 确实做到了这一点,参见 JvmtiTagMap::do_weak_oops.