Озадачен поведением обратного вызова выделения объектов jvmti - PullRequest
1 голос
/ 25 марта 2012

Может кто-нибудь объяснить мне, почему я могу получить обратный вызов, когда jvm выделяет некоторые объекты Java, но не другие? Вот что я делаю:

static jvmtiCapabilities    capa;
static jvmtiEnv*            jvmti                   = NULL;
static const char*          fileName                = "C:\\temp\\ObjectInitCallbackDump.txt";
static ofstream             outFileStream;

void JNICALL callbackObjectAllocation ( jvmtiEnv*   jvmti_env, 
                                        JNIEnv*     jni_env,
                                        jthread     thread,
                                        jobject     object,
                                        jclass      object_klass,
                                        jlong       size            )
{
    char*       generic_ptr_class;
    char*       class_name;
    jvmtiError  error;

    error = jvmti_env->GetClassSignature(object_klass, &class_name, &generic_ptr_class);
    if (check_jvmti_error(jvmti_env, error, "Failed to get class signature")) {
        return;
    }
    outFileStream << class_name << std::endl;
}

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
    jint                result;
    jvmtiError          error;
    jvmtiEventCallbacks callbacks;

    outFileStream.open(fileName,ios::trunc);

    result  = jvm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_1);
    if (result != JNI_OK || jvmti == NULL) {
        printf("error\n");
        return JNI_ERR;
    } else {
        printf("loaded agent\n");
    }

    (void) memset(&capa, 0, sizeof(jvmtiCapabilities));
    capa.can_generate_vm_object_alloc_events        = 1;

    error = jvmti->AddCapabilities(&capa);
    if (check_jvmti_error(jvmti, error, "Unable to set capabilities") != JNI_OK) {
        return JNI_ERR;
    }

    (void) memset(&callbacks, 0, sizeof(callbacks));
    callbacks.VMObjectAlloc         = &callbackObjectAllocation;

    error = jvmti->SetEventCallbacks(&callbacks, (jint) sizeof(callbacks));
    if (check_jvmti_error(jvmti, error, "Unable to set callbacks") != JNI_OK) {
        return JNI_ERR;
    }

    error = jvmti->SetEventNotificationMode(    JVMTI_ENABLE,
                                                JVMTI_EVENT_VM_OBJECT_ALLOC,
                                                (jthread) NULL);
    if (check_jvmti_error(jvmti, error,
            "Unable to set method entry notifications") != JNI_OK) {
        return JNI_ERR;
    }

    return JNI_OK;
}

JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
    outFileStream.close();
}

Когда я проверяю файл, который я создаю, я не вижу интересующие меня классы, хотя я знаю, что они есть, и NetBeans сообщает мне, что в jvm есть только один экземпляр этого класса. Есть мысли ???

Nikita

Ответы [ 2 ]

9 голосов
/ 16 июля 2012

По соображениям производительности JVMTI поддерживает только события выделения для объектов, которые не могут быть обнаружены с помощью инструментария байт-кода (BCI), как объяснено в документации по событиям JVMTI VMObjectAlloc. Это означает, что событие не будет вызвано для большинства назначений объектов. Я предполагаю, что недостающие средства попадают в эту категорию.

К счастью, на самом деле не так уж сложно перехватить все распределения объектов с использованием BCI. Демонстрация HeapTracker точно иллюстрирует, как перехватывать все выделения объектов в агенте JVMTI, используя java_crw_demo в дополнение к событиям VMObjectAlloc.

0 голосов
/ 25 марта 2012

Может быть, вы просто не попали в чек? Если это код, который вы на самом деле выполняете, значит, у вас ошибка ты пропустил; в конце объекта Ваше сравнение должно быть таким:

if (strcmp(class_name,"Ljavax/swing/JFrame;") == 0) {
    printf("Got the sucker!!!");
}
...