Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/Heap/libIterateHeapWithEscapeAnalysisEnabled.cpp
41153 views
/*1* Copyright (c) 2020 SAP SE. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include <stdio.h>24#include <string.h>25#include "jvmti.h"26#include "jni.h"2728extern "C" {2930#define FAILED -131#define OK 03233static jvmtiEnv *jvmti;3435static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);3637static void ShowErrorMessage(jvmtiEnv *jvmti, jvmtiError errCode, const char *message) {38char *errMsg;39jvmtiError result;4041result = jvmti->GetErrorName(errCode, &errMsg);42if (result == JVMTI_ERROR_NONE) {43fprintf(stderr, "%s: %s (%d)\n", message, errMsg, errCode);44jvmti->Deallocate((unsigned char *)errMsg);45} else {46fprintf(stderr, "%s (%d)\n", message, errCode);47}48}4950JNIEXPORT jint JNICALL51Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {52return Agent_Initialize(jvm, options, reserved);53}5455JNIEXPORT jint JNICALL56Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {57return Agent_Initialize(jvm, options, reserved);58}5960JNIEXPORT jint JNICALL61JNI_OnLoad(JavaVM *jvm, void *reserved) {62jint res;63JNIEnv *env;6465res = jvm->GetEnv((void **) &env, JNI_VERSION_9);66if (res != JNI_OK || env == NULL) {67fprintf(stderr, "Error: GetEnv call failed(%d)!\n", res);68return JNI_ERR;69}7071return JNI_VERSION_9;72}7374static jint75Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {76jint res;7778printf("Agent_OnLoad started\n");7980res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_9);81if (res != JNI_OK || jvmti == NULL) {82fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");83return JNI_ERR;84}8586printf("Agent_OnLoad finished\n");87return JNI_OK;88}8990JNIEXPORT jint JNICALL91Java_IterateHeapWithEscapeAnalysisEnabled_acquireCanTagObjectsCapability(JNIEnv *env, jclass cls) {92jvmtiError err;93jvmtiCapabilities caps;9495memset(&caps, 0, sizeof(caps));9697caps.can_tag_objects = 1;9899err = jvmti->AddCapabilities(&caps);100if (err != JVMTI_ERROR_NONE) {101ShowErrorMessage(jvmti, err,102"acquireCanTagObjectsCapability: error in JVMTI AddCapabilities");103return JNI_ERR;104}105106err = jvmti->GetCapabilities(&caps);107if (err != JVMTI_ERROR_NONE) {108ShowErrorMessage(jvmti, err,109"acquireCanTagObjectsCapability: error in JVMTI GetCapabilities");110return JNI_ERR;111}112113if (!caps.can_tag_objects) {114fprintf(stderr, "Warning: didn't get the capability can_tag_objects\n");115return JNI_ERR;116}117118return JNI_OK;119}120121static jobject method_IterateOverReachableObjects;122static jobject method_IterateOverHeap;123static jobject method_IterateOverInstancesOfClass;124static jobject method_FollowReferences;125static jobject method_IterateThroughHeap;126127JNIEXPORT jint JNICALL128Java_IterateHeapWithEscapeAnalysisEnabled_registerMethod(JNIEnv *env, jclass cls, jobject method, jstring name) {129const char *name_chars = env->GetStringUTFChars(name, 0);130int rc = FAILED;131if (rc != OK && strcmp(name_chars, "IterateOverReachableObjects") == 0) {132method_IterateOverReachableObjects = env->NewGlobalRef(method);133rc = OK;134}135if (rc != OK && strcmp(name_chars, "IterateOverHeap") == 0) {136method_IterateOverHeap = env->NewGlobalRef(method);137rc = OK;138}139if (rc != OK && strcmp(name_chars, "IterateOverInstancesOfClass") == 0) {140method_IterateOverInstancesOfClass = env->NewGlobalRef(method);141rc = OK;142}143if (rc != OK && strcmp(name_chars, "IterateThroughHeap") == 0) {144method_IterateThroughHeap = env->NewGlobalRef(method);145rc = OK;146}147if (rc != OK && strcmp(name_chars, "FollowReferences") == 0) {148method_FollowReferences = env->NewGlobalRef(method);149rc = OK;150}151env->ReleaseStringUTFChars(name, name_chars);152return rc;153}154155JNIEXPORT void JNICALL156Java_IterateHeapWithEscapeAnalysisEnabled_agentTearDown(JNIEnv *env, jclass cls) {157env->DeleteGlobalRef(method_IterateOverReachableObjects);158env->DeleteGlobalRef(method_IterateOverHeap);159env->DeleteGlobalRef(method_IterateOverInstancesOfClass);160env->DeleteGlobalRef(method_FollowReferences);161env->DeleteGlobalRef(method_IterateThroughHeap);162}163164JNIEXPORT jint JNICALL165Java_IterateHeapWithEscapeAnalysisEnabled_jvmtiTagClass(JNIEnv *env, jclass cls, jclass clsToTag, jlong tag) {166jvmtiError err;167err = jvmti->SetTag(clsToTag, tag);168if (err != JVMTI_ERROR_NONE) {169ShowErrorMessage(jvmti, err,170"jvmtiTagClass: error in JVMTI SetTag");171return FAILED;172}173return OK;174}175176typedef struct Tag_And_Counter {177jlong instance_counter;178jlong class_tag;179jlong instance_tag;180} Tag_And_Counter;181182static jvmtiIterationControl JNICALL183__stackReferenceCallback(jvmtiHeapRootKind root_kind,184jlong class_tag,185jlong size,186jlong* tag_ptr,187jlong thread_tag,188jint depth,189jmethodID method,190jint slot,191void* d) {192Tag_And_Counter* data = (Tag_And_Counter*) d;193if (class_tag == data->class_tag && *tag_ptr == 0) {194data->instance_counter++;195*tag_ptr = data->instance_tag;196}197return JVMTI_ITERATION_CONTINUE;198}199200static jvmtiIterationControl JNICALL201__jvmtiHeapObjectCallback(jlong class_tag, jlong size, jlong* tag_ptr, void* d) {202Tag_And_Counter* data = (Tag_And_Counter*) d;203if (class_tag == data->class_tag && *tag_ptr == 0) {204data->instance_counter++;205*tag_ptr = data->instance_tag;206}207return JVMTI_ITERATION_CONTINUE;208}209210static jint JNICALL211__jvmtiHeapReferenceCallback(jvmtiHeapReferenceKind reference_kind,212const jvmtiHeapReferenceInfo* reference_info,213jlong class_tag,214jlong referrer_class_tag,215jlong size,216jlong* tag_ptr,217jlong* referrer_tag_ptr,218jint length,219void* d) {220Tag_And_Counter* data = (Tag_And_Counter*) d;221if (class_tag == data->class_tag && *tag_ptr == 0) {222data->instance_counter++;223*tag_ptr = data->instance_tag;224}225return JVMTI_VISIT_OBJECTS;226}227228static jint JNICALL229__jvmtiHeapIterationCallback(jlong class_tag,230jlong size,231jlong* tag_ptr,232jint length,233void* d) {234Tag_And_Counter* data = (Tag_And_Counter*) d;235if (class_tag == data->class_tag && *tag_ptr == 0) {236data->instance_counter++;237*tag_ptr = data->instance_tag;238}239return JVMTI_VISIT_OBJECTS;240}241242243JNIEXPORT jlong JNICALL244Java_IterateHeapWithEscapeAnalysisEnabled_countAndTagInstancesOfClass(JNIEnv *env,245jclass cls,246jclass tagged_class,247jlong cls_tag,248jlong instance_tag,249jobject method) {250jvmtiError err;251jvmtiHeapCallbacks callbacks = {};252Tag_And_Counter data = {0, cls_tag, instance_tag};253jboolean method_found = JNI_FALSE;254255jint idx = 0;256257if (env->IsSameObject(method, method_IterateOverReachableObjects)) {258method_found = JNI_TRUE;259err = jvmti->IterateOverReachableObjects(NULL /*jvmtiHeapRootCallback*/,260__stackReferenceCallback,261NULL /* jvmtiObjectReferenceCallback */,262&data);263if (err != JVMTI_ERROR_NONE) {264ShowErrorMessage(jvmti, err,265"countAndTagInstancesOfClass: error in JVMTI IterateOverReachableObjects");266return FAILED;267}268}269if (env->IsSameObject(method, method_IterateOverHeap)) {270method_found = JNI_TRUE;271err = jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER,272__jvmtiHeapObjectCallback,273&data);274if (err != JVMTI_ERROR_NONE) {275ShowErrorMessage(jvmti, err,276"countAndTagInstancesOfClass: error in JVMTI IterateOverHeap");277return FAILED;278}279}280if (env->IsSameObject(method, method_IterateOverInstancesOfClass)) {281method_found = JNI_TRUE;282err = jvmti->IterateOverInstancesOfClass(tagged_class,283JVMTI_HEAP_OBJECT_EITHER,284__jvmtiHeapObjectCallback,285&data);286if (err != JVMTI_ERROR_NONE) {287ShowErrorMessage(jvmti, err,288"countAndTagInstancesOfClass: error in JVMTI IterateOverHeap");289return FAILED;290}291}292if (env->IsSameObject(method, method_FollowReferences)) {293method_found = JNI_TRUE;294callbacks.heap_reference_callback = __jvmtiHeapReferenceCallback;295err = jvmti->FollowReferences(0 /* filter nothing */,296NULL /* no class filter */,297NULL /* no initial object, follow roots */,298&callbacks,299&data);300if (err != JVMTI_ERROR_NONE) {301ShowErrorMessage(jvmti, err,302"countAndTagInstancesOfClass: error in JVMTI FollowReferences");303return FAILED;304}305}306if (env->IsSameObject(method, method_IterateThroughHeap)) {307method_found = JNI_TRUE;308callbacks.heap_iteration_callback = __jvmtiHeapIterationCallback;309err = jvmti->IterateThroughHeap(0 /* filter nothing */,310NULL /* no class filter */,311&callbacks,312&data);313if (err != JVMTI_ERROR_NONE) {314ShowErrorMessage(jvmti, err,315"countAndTagInstancesOfClass: error in JVMTI IterateThroughHeap");316return FAILED;317}318}319320if (!method_found) {321fprintf(stderr, "countAndTagInstancesOfClass: unknown method\n");322return FAILED;323}324325return data.instance_counter;326}327328JNIEXPORT jlong JNICALL329Java_IterateHeapWithEscapeAnalysisEnabled_getObjectsWithTag(JNIEnv *env,330jclass cls,331jlong tag,332jobjectArray res_instances) {333jvmtiError err;334const jlong tags[1] = {tag};335jint res_count = -1;336jobject* res_instances_raw;337jlong* res_tags;338jint res_instances_length;339jint idx;340341err = jvmti->GetObjectsWithTags(1,342tags,343&res_count,344&res_instances_raw,345&res_tags);346if (err != JVMTI_ERROR_NONE) {347ShowErrorMessage(jvmti, err,348"getObjectsWithTags: error in JVMTI GetObjectsWithTags");349return FAILED;350}351352res_instances_length = env->GetArrayLength(res_instances);353if (res_count != res_instances_length) {354fprintf(stderr, "getObjectsWithTags: result array lenght (%d) does not match instance count returned by GetObjectsWithTags (%d) \n",355res_instances_length, res_count);356return FAILED;357}358359for (idx = 0; idx < res_count; idx++) {360env->SetObjectArrayElement(res_instances, idx, res_instances_raw[idx]);361}362363jvmti->Deallocate((unsigned char *)res_instances_raw);364jvmti->Deallocate((unsigned char *)res_tags);365366return OK;367}368369}370371372