Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp
40955 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. 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 <stdlib.h>25#include <string.h>26#include "jvmti.h"27#include "agent_common.h"28#include "JVMTITools.h"29#include "jvmti_tools.h"3031extern "C" {323334#define PASSED 035#define STATUS_FAILED 236#define MAX_THREADS 323738typedef struct item *item_t;39struct item {40item_t next;41jmethodID method;42int depth;43} item;4445typedef struct thr {46jthread thread;47item_t tos;48} thr;4950static jvmtiEnv *jvmti = NULL;51static jvmtiCapabilities caps;52static jvmtiEventCallbacks callbacks;53static jrawMonitorID event_lock;54static jint result = PASSED;55static jboolean printdump = JNI_FALSE;56static jboolean watch_events = JNI_FALSE;5758static int pop_count = 0;59static int push_count = 0;60static int thr_count = 0;61static int max_depth = 0;62static thr threads[MAX_THREADS];6364static volatile int callbacksEnabled = NSK_FALSE;65static jrawMonitorID agent_lock;6667static68int isTestThread(jvmtiEnv *jvmti_env, jthread thr) {69jvmtiError err;70jvmtiThreadInfo inf;71const char* TEST_THREAD_NAME_BASE = "Test Thread";7273err = jvmti_env->GetThreadInfo(thr, &inf);74if (err != JVMTI_ERROR_NONE) {75printf("(GetThreadInfo) unexpected error: %s (%d)\n", TranslateError(err), err);76result = STATUS_FAILED;77return 0;78}79return strncmp(inf.name, TEST_THREAD_NAME_BASE, strlen(TEST_THREAD_NAME_BASE)) == 0;80}8182static83void printInfo(jvmtiEnv *jvmti_env, jthread thr, jmethodID method, int depth) {84jvmtiError err;85jvmtiThreadInfo inf;86char *clsig, *name, *sig, *generic;87jclass cls;8889err = jvmti_env->GetThreadInfo(thr, &inf);90if (err != JVMTI_ERROR_NONE) {91printf("(GetThreadInfo) unexpected error: %s (%d)\n",92TranslateError(err), err);93result = STATUS_FAILED;94}9596err = jvmti_env->GetMethodDeclaringClass(method, &cls);97if (err != JVMTI_ERROR_NONE) {98printf("(GetMethodDeclaringClass) unexpected error: %s (%d)\n",99TranslateError(err), err);100result = STATUS_FAILED;101return;102}103104err = jvmti_env->GetClassSignature(cls, &clsig, &generic);105if (err != JVMTI_ERROR_NONE) {106printf("(GetClassSignature) unexpected error: %s (%d)\n",107TranslateError(err), err);108result = STATUS_FAILED;109return;110}111112err = jvmti_env->GetMethodName(method, &name, &sig, &generic);113if (err != JVMTI_ERROR_NONE) {114printf("(GetMethodName) unexpected error: %s (%d)\n",115TranslateError(err), err);116result = STATUS_FAILED;117return;118}119120printf(" %s: %s.%s%s, depth = %d\n", inf.name, clsig, name, sig, depth);121122jvmti_env->Deallocate((unsigned char *)sig);123jvmti_env->Deallocate((unsigned char *)name);124jvmti_env->Deallocate((unsigned char *)clsig);125jvmti_env->Deallocate((unsigned char *)inf.name);126}127128static129void pop(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr, jmethodID method, int depth) {130item_t old;131int i, count = 0;132133for (i = 0; i < thr_count; i++) {134if (env->IsSameObject(threads[i].thread, thr)) {135break;136}137}138139if (i == thr_count) {140watch_events = JNI_FALSE;141printf("Unknown thread:\n");142printInfo(jvmti_env, thr, method, depth);143result = STATUS_FAILED;144return;145}146147if (threads[i].tos == NULL) {148watch_events = JNI_FALSE;149printf("Stack underflow:\n");150printInfo(jvmti_env, thr, method, depth);151result = STATUS_FAILED;152return;153}154155do {156pop_count++;157old = threads[i].tos;158threads[i].tos = threads[i].tos->next;159if (old->method == method && old->depth == depth) {160free(old);161return;162}163free(old);164} while (threads[i].tos != NULL);165166watch_events = JNI_FALSE;167printf("Frame pop does not match any entry:\n");168printInfo(jvmti_env, thr, method, depth);169result = STATUS_FAILED;170}171172static173void push(JNIEnv *env, jthread thr, jmethodID method, int depth) {174item_t new_item;175int i;176177for (i = 0; i < thr_count; i++) {178if (env->IsSameObject(threads[i].thread, thr)) {179break;180}181}182183if (i == thr_count) {184thr_count++;185if (thr_count == MAX_THREADS) {186watch_events = JNI_FALSE;187printf("Out of threads\n");188result = STATUS_FAILED;189return;190}191threads[i].thread = env->NewGlobalRef(thr);192threads[i].tos = NULL;193}194195new_item = (item_t)malloc(sizeof(item));196if (new_item == NULL) {197watch_events = JNI_FALSE;198printf("Out of memory\n");199result = STATUS_FAILED;200return;201}202203new_item->next = threads[i].tos;204new_item->method = method;205new_item->depth = depth;206threads[i].tos = new_item;207push_count++;208max_depth = (max_depth < depth) ? depth : max_depth;209}210211void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env,212jthread thr, jmethodID method) {213jvmtiError err;214jboolean isNative;215jint frameCount;216217if (watch_events == JNI_FALSE) return;218219jvmti->RawMonitorEnter(agent_lock);220221if (!callbacksEnabled) {222jvmti->RawMonitorExit(agent_lock);223return;224}225226err = jvmti_env->GetFrameCount(thr, &frameCount);227if (err != JVMTI_ERROR_NONE) {228printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",229TranslateError(err), err);230printInfo(jvmti_env, thr, method, frameCount);231result = STATUS_FAILED;232jvmti->RawMonitorExit(agent_lock);233return;234}235236err = jvmti_env->IsMethodNative(method, &isNative);237if (err != JVMTI_ERROR_NONE) {238printf("(IsMethodNative) unexpected error: %s (%d)\n",239TranslateError(err), err);240printInfo(jvmti_env, thr, method, frameCount);241result = STATUS_FAILED;242}243244if (isTestThread(jvmti_env, thr)) {245if (printdump == JNI_TRUE) {246printf(">>> %sMethod entry\n>>>",247(isNative == JNI_TRUE) ? "Native " : "");248printInfo(jvmti_env, thr, method, frameCount);249}250if (isNative == JNI_FALSE) {251err = jvmti_env->RawMonitorEnter(event_lock);252if (err != JVMTI_ERROR_NONE) {253printf("(RawMonitorEnter) unexpected error: %s (%d)\n",254TranslateError(err), err);255printInfo(jvmti_env, thr, method, frameCount);256result = STATUS_FAILED;257}258push((JNIEnv *)env, thr, method, frameCount);259err = jvmti_env->RawMonitorExit(event_lock);260if (err != JVMTI_ERROR_NONE) {261printf("(RawMonitorExit) unexpected error: %s (%d)\n",262TranslateError(err), err);263printInfo(jvmti_env, thr, method, frameCount);264result = STATUS_FAILED;265}266err = jvmti_env->NotifyFramePop(thr, 0);267if (err != JVMTI_ERROR_NONE) {268printf("(NotifyFramePop) unexpected error: %s (%d)\n",269TranslateError(err), err);270printInfo(jvmti_env, thr, method, frameCount);271result = STATUS_FAILED;272}273}274}275276jvmti->RawMonitorExit(agent_lock);277}278279void JNICALL VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {280jvmti->RawMonitorEnter(agent_lock);281282callbacksEnabled = NSK_TRUE;283284jvmti->RawMonitorExit(agent_lock);285}286287288void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {289jvmti->RawMonitorEnter(agent_lock);290291callbacksEnabled = NSK_FALSE;292293jvmti->RawMonitorExit(agent_lock);294}295296void JNICALL FramePop(jvmtiEnv *jvmti_env, JNIEnv *env,297jthread thr, jmethodID method, jboolean wasPopedByException) {298jvmtiError err;299jint frameCount;300301jvmti->RawMonitorEnter(agent_lock);302303if (!callbacksEnabled) {304jvmti->RawMonitorExit(agent_lock);305return;306}307err = jvmti_env->GetFrameCount(thr, &frameCount);308if (err != JVMTI_ERROR_NONE) {309printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",310TranslateError(err), err);311printInfo(jvmti_env, thr, method, frameCount);312result = STATUS_FAILED;313jvmti->RawMonitorExit(agent_lock);314return;315}316317if (isTestThread(jvmti_env, thr)) {318if (printdump == JNI_TRUE) {319printf(">>> Frame Pop\n>>>");320printInfo(jvmti_env, thr, method, frameCount);321}322err = jvmti_env->RawMonitorEnter(event_lock);323if (err != JVMTI_ERROR_NONE) {324printf("(RawMonitorEnter) unexpected error: %s (%d)\n",325TranslateError(err), err);326printInfo(jvmti_env, thr, method, frameCount);327result = STATUS_FAILED;328}329pop(jvmti_env, (JNIEnv *)env, thr, method, frameCount);330err = jvmti_env->RawMonitorExit(event_lock);331if (err != JVMTI_ERROR_NONE) {332printf("(RawMonitorExit) unexpected error: %s (%d)\n",333TranslateError(err), err);334printInfo(jvmti_env, thr, method, frameCount);335result = STATUS_FAILED;336}337}338339jvmti->RawMonitorExit(agent_lock);340}341342#ifdef STATIC_BUILD343JNIEXPORT jint JNICALL Agent_OnLoad_framepop002(JavaVM *jvm, char *options, void *reserved) {344return Agent_Initialize(jvm, options, reserved);345}346JNIEXPORT jint JNICALL Agent_OnAttach_framepop002(JavaVM *jvm, char *options, void *reserved) {347return Agent_Initialize(jvm, options, reserved);348}349JNIEXPORT jint JNI_OnLoad_framepop002(JavaVM *jvm, char *options, void *reserved) {350return JNI_VERSION_1_8;351}352#endif353jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {354jvmtiError err;355jint res;356357if (options != NULL && strcmp(options, "printdump") == 0) {358printdump = JNI_TRUE;359}360361res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);362if (res != JNI_OK || jvmti == NULL) {363printf("Wrong result of a valid call to GetEnv!\n");364return JNI_ERR;365}366367err = jvmti->CreateRawMonitor("_event_lock", &event_lock);368if (err != JVMTI_ERROR_NONE) {369printf("(CreateRawMonitor) unexpected error: %s (%d)\n",370TranslateError(err), err);371return JNI_ERR;372}373374err = jvmti->GetPotentialCapabilities(&caps);375if (err != JVMTI_ERROR_NONE) {376printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",377TranslateError(err), err);378return JNI_ERR;379}380381err = jvmti->AddCapabilities(&caps);382if (err != JVMTI_ERROR_NONE) {383printf("(AddCapabilities) unexpected error: %s (%d)\n",384TranslateError(err), err);385return JNI_ERR;386}387388err = jvmti->GetCapabilities(&caps);389if (err != JVMTI_ERROR_NONE) {390printf("(GetCapabilities) unexpected error: %s (%d)\n",391TranslateError(err), err);392return JNI_ERR;393}394395if (caps.can_generate_frame_pop_events &&396caps.can_generate_method_entry_events) {397callbacks.MethodEntry = &MethodEntry;398callbacks.FramePop = &FramePop;399callbacks.VMStart = &VMStart;400callbacks.VMDeath = &VMDeath;401402err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));403if (err != JVMTI_ERROR_NONE) {404printf("(SetEventCallbacks) unexpected error: %s (%d)\n",405TranslateError(err), err);406return JNI_ERR;407}408if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))409return JNI_ERR;410if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))411return JNI_ERR;412413if (jvmti->CreateRawMonitor("agent_lock", &agent_lock) != JVMTI_ERROR_NONE) {414return JNI_ERR;415}416417} else {418printf("Warning: FramePop or MethodEntry event is not implemented\n");419}420421return JNI_OK;422}423424JNIEXPORT void JNICALL Java_nsk_jvmti_FramePop_framepop002_getReady(JNIEnv *env, jclass cls) {425jvmtiError err;426427if (!caps.can_generate_frame_pop_events ||428!caps.can_generate_method_entry_events) {429return ;430}431432err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,433JVMTI_EVENT_METHOD_ENTRY, NULL);434if (err != JVMTI_ERROR_NONE) {435printf("Failed to enable JVMTI_EVENT_METHOD_ENTRY event: %s (%d)\n",436TranslateError(err), err);437result = STATUS_FAILED;438}439err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,440JVMTI_EVENT_FRAME_POP, NULL);441if (err != JVMTI_ERROR_NONE) {442printf("Failed to enable JVMTI_EVENT_FRAME_POP event: %s (%d)\n",443TranslateError(err), err);444result = STATUS_FAILED;445}446watch_events = JNI_TRUE;447}448449JNIEXPORT jint JNICALL Java_nsk_jvmti_FramePop_framepop002_check(JNIEnv *env, jclass cls) {450jvmtiError err;451452watch_events = JNI_FALSE;453err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,454JVMTI_EVENT_FRAME_POP, NULL);455if (err != JVMTI_ERROR_NONE) {456printf("Failed to disable JVMTI_EVENT_FRAME_POP event: %s (%d)\n",457TranslateError(err), err);458result = STATUS_FAILED;459}460err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,461JVMTI_EVENT_METHOD_ENTRY, NULL);462if (err != JVMTI_ERROR_NONE) {463printf("Failed to disable JVMTI_EVENT_METHOD_ENTRY event: %s (%d)\n",464TranslateError(err), err);465result = STATUS_FAILED;466}467468if (printdump == JNI_TRUE) {469printf("%d threads, %d method entrys, %d frame pops, max depth = %d\n",470thr_count, push_count, pop_count, max_depth);471}472473return result;474}475476}477478479