【问题标题】:Java API on top of JVMTI?JVMTI 之上的 Java API?
【发布时间】:2011-06-16 16:30:13
【问题描述】:

有没有可以在 JVMTI 之上使用的不错的 Java API?

【问题讨论】:

  • 您想使用 JVMTI 的哪一部分?很多它不可能简单地包装在java中,因为它用于监视java的方式如果你从java代码中执行它会导致非常不可预测的情况。对于某些事件,当然可以编写一个可以从 java 访问的本机 JVMTI 后端,但我想不出与其他替代方案相比它会非常有用的情况。
  • 看完所有答案后,我意识到我可能完全误解了 JVMTI 应该做什么。我可能应该使用仪器 API,因为我想构建仪器应用程序
  • “最接近金属”的 JVMTI Java 包装器可能是 Java 调试接口,它在与被调试的 JVM 不同的 JVM 中运行(通常 JVM 由套接字连接)。文档推荐这种连接到 JVM 调试实用程序的方法,而不是直接从同一进程中的本机代码使用 JVMTI。您可以找到更多关于调试器架构和 JDI 提供的抽象here 的文档。

标签: java jvmti


【解决方案1】:

JVMTI 并不是为了在上面放置 Java API 而构建的。 JVM TI 定义本身说:

JVM 工具接口 (JVM TI) 是一个标准原生 API,允许原生库捕获事件并控制 Java 平台的 Java 虚拟机 (JVM)。

由于它是为本地 API 构建来捕获事件和控件的,我认为它上面没有 API。您能解释一下您要达到的目标吗?

我不知道任何基于 JVM TI 的 Java API。

【讨论】:

  • 只是想用Java 构建一个工具来控制另一个JVM。考虑一个分析器或类似的东西。这将使调试一些奇怪的问题更容易。
  • 好吧,JVMTI API 真正漂亮的部分在 Java 中是无用的......而对于其他一切,还有 java.lang.instrument!
【解决方案2】:

好的...刚刚尝试过...似乎按预期工作....在现实生活中,VMInit 回调将返回一个类的实例,该实例实现了一个镜像 C JVMTI 接口的接口.... C 代理将存储此实例并在事件需要时调用它....另外,在 VMInit Java 返回之前,它会设置功能和回调并注册事件等....您可能可以获得大约 90% 的 JVMTI API覆盖范围.....这只是输入它的一个例子......如果你有一个强有力的案例,我可以在一个周末完成:-)

下面的代码产生这个:

C:VMInit,准备回调Java方法
Java:JVMTI 回调类,VMInit()。
C:VMInit,回调Java方法成功返回
Java:最后...您好,我是 Java 主力


package com.stackoverflow;

public class JVMTICallback {

    public static void VMInit() {

        System.out.println("Java:\tJVMTI callback class, VMInit().");

    }

    public static void main(String[] args) {
        // This main is only here to give us something to run for the test

        System.out.println("Java:\tAnd Finally... Hello, I'm the Java main");
    }

}

和C

#include <stdlib.h>
#include "jvmti.h"

jvmtiEnv *globalJVMTIInterface;

void JNICALL
vmInit(jvmtiEnv * jvmti_env, JNIEnv * jni_env, jthread thread)
{

  printf("C:\tVMInit, preparing to callback Java method\n");

  char *className = "com/stackoverflow/JVMTICallback";
  char *methodName = "VMInit";
  char *descriptor = "()V";

  jclass callbackClass = (*jni_env)->FindClass(jni_env, className);

  if (!callbackClass) {
      fprintf(stderr,"C:\tUnable to locate callback class.\n");
      return;
      }

  jmethodID callbackMethodID = (*jni_env)->GetStaticMethodID(jni_env, callbackClass, methodName, descriptor);

  if (!callbackMethodID)
    {
      fprintf(stderr, "C:\tUnable to locate callback VMInit method\n");
      return;
    }

  (*jni_env)->CallStaticVoidMethodV(jni_env, callbackClass, callbackMethodID, NULL);

  printf("C:\tVMInit, callback Java method returned successfully\n");


}

JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM * jvm, char *options, void *reserved)
{

  jint returnCode = (*jvm)->GetEnv(jvm, (void **) &globalJVMTIInterface,
      JVMTI_VERSION_1_0);

  if (returnCode != JNI_OK)
    {
      fprintf(stderr,
          "The version of JVMTI requested (1.0) is not supported by this JVM.\n");
      return JVMTI_ERROR_UNSUPPORTED_VERSION;
    }

  jvmtiEventCallbacks *eventCallbacks;

  eventCallbacks = calloc(1, sizeof(jvmtiEventCallbacks));
  if (!eventCallbacks)
    {
      fprintf(stderr, "Unable to allocate memory\n");
      return JVMTI_ERROR_OUT_OF_MEMORY;
    }

  eventCallbacks->VMInit = &vmInit;

  returnCode = (*globalJVMTIInterface)->SetEventCallbacks(globalJVMTIInterface,
      eventCallbacks, (jint) sizeof(*eventCallbacks));
  if (returnCode != JNI_OK)
    {
      fprintf(stderr, "C:\tJVM does not have the required capabilities (%d)\n",
          returnCode);
      exit(-1);
    }

  returnCode = (*globalJVMTIInterface)->SetEventNotificationMode(
      globalJVMTIInterface, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, (jthread) NULL);
  if (returnCode != JNI_OK)
    {
      fprintf(
          stderr,
          "C:\tJVM does not have the required capabilities, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT (%d)\n",
          returnCode);
      exit(-1);
    }

  return JVMTI_ERROR_NONE;
}

【讨论】:

    【解决方案3】:

    我四处搜索,不幸的是在 JVMTI 之上找不到任何 Java API 库。看来你倒霉了。

    您可以做的是从您的 Java 代码中调用本机库。我不太擅长 C/C++,但从 JVMTI 文档中我看到可以从 provided headers 构建一个小型共享库。然后您可以使用 JNA** 调用它。它将为您提供一个很好的原生库 API 包装器。

    看看JNA Getting Started page的例子

    此页面还链接到JNAerator,它可以为您生成所有必要的 Java 绑定。

    这种方法的缺点是必须为您的目标平台维护这个薄的原生层。


    ** 与通常的 JNI 相比,JNA 处理运行时开销,但易于开发超过了 IMO 的性能优势。仅当您到时才切换到 JNI。

    【讨论】:

      【解决方案4】:

      它不会起作用。 JVMTI 具有 Java 代码无法直接控制的回调(如 ClassPrepare)。如果这些回调是用Java实现的,执行时可能会导致其他回调导致死锁。

      【讨论】:

        【解决方案5】:

        编写起来并不难......只需通过 JVMTI 调用通过 JNI 回调一个 Java 类......你可能会面临几个问题......首先是 Agent_onLoad..这个初始“注册”函数在 JVM 的生命周期中发生得太早,无法回调您的 java....其次,存在潜在的循环问题以及 JVM 的编写可能期望您在...上执行类似的操作...

        我试着写一个例子....几分钟后回来...

        【讨论】:

          【解决方案6】:

          JDI是用Java编写的顶级接口,使用JVMTI作为后端api。 this link给你详细信息。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-02-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-12
            • 1970-01-01
            • 2017-09-19
            相关资源
            最近更新 更多