15

我可以在 JVMTI 之上使用一个不错的 Java API 吗?

4

6 回答 6

12

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

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

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

我不知道 JVM TI 之上的任何 Java API。

于 2011-01-31T05:41:03.230 回答
5

好的......刚刚尝试过......似乎按预期工作......在现实生活中,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;
}
于 2011-02-07T18:59:26.487 回答
3

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

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

查看JNA 入门页面中的示例

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

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


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

于 2011-02-04T11:24:17.103 回答
2

It will not work. JVMTI has callbacks that the Java code has no direct control over (like ClassPrepare). If these callbacks are implemented in Java, the execution can lead other callbacks causing deadlock.

于 2014-08-04T15:41:35.783 回答
1

JDI是用Java编写的TOP级接口,使用JVMTI作为后端api。 此链接为您提供详细信息。

于 2014-09-14T13:37:49.243 回答
1

编写起来并不难.. 只需通过 JNI 调用 JVMTI 调用来回调 Java 类.. 你可能会面临几个问题......首先是 Agent_onLoad.. 这个初始的“注册”功能也会发生在 JVM 生命周期的早期,它会回调您的 java....其次,存在潜在的循环问题以及 JVM 的编写可能期望您在...

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

于 2011-02-07T18:23:40.513 回答