Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp
40951 views
/*1* Copyright (c) 2007, 2019, 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*/22#include <stdio.h>23#include <stdlib.h>24#include <string.h>25#include <jni.h>26#include <jvmti.h>27#include <aod.h>28#include <jvmti_aod.h>29#include "ExceptionCheckingJniEnv.hpp"3031extern "C" {3233/*34* Expected agent work scenario:35* - receive ClassFileLoadHook event for class 'ClassToRedefine'36* - receive ClassLoad event for class 'ClassToRedefine' and redefine class from ClassLoad event handler37* - receive one more ClassFileLoadHook event for class 'ClassToRedefine'38* - receive ClassPrepare event for class 'ClassToRedefine' and finish work39*/4041#define REDEFINED_CLASS_NAME "Lnsk/jvmti/AttachOnDemand/attach002/ClassToRedefine;"42#define REDEFINED_CLASS_FILE_NAME "nsk/jvmti/AttachOnDemand/attach002/ClassToRedefine"4344// class name in the ClassFileLoadHook callback45#define REDEFINED_CLASS_NAME_INTERNAL "nsk/jvmti/AttachOnDemand/attach002/ClassToRedefine"4647static Options* options = NULL;48static const char* agentName;4950static volatile jboolean agentGotCapabilities = JNI_FALSE;5152static jvmtiEvent testEvents[] = {53JVMTI_EVENT_CLASS_LOAD,54JVMTI_EVENT_CLASS_PREPARE,55JVMTI_EVENT_CLASS_FILE_LOAD_HOOK };5657static const int testEventsNumber = 3;5859static volatile int classLoadReceived = 0;60static volatile int classFileLoadHookReceived = 0;6162JNIEXPORT jboolean JNICALL63Java_nsk_jvmti_AttachOnDemand_attach002_attach002Target_agentGotCapabilities(JNIEnv * jni,64jclass klass, jobject obj) {65return agentGotCapabilities;66}6768#define ATTACH002_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach002/attach002Target"6970void registerNativeMethods(JNIEnv* jni_env) {71ExceptionCheckingJniEnvPtr ec_jni(jni_env);72jclass appClass;73JNINativeMethod nativeMethods[] = {74{ (char*) "agentGotCapabilities", (char*) "()Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach002_attach002Target_agentGotCapabilities } };75jint nativeMethodsNumber = 1;7677appClass = ec_jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL);78ec_jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL);79}8081void JNICALL classLoadHandler(82jvmtiEnv *jvmti,83JNIEnv* jni,84jthread thread,85jclass klass) {86char className[MAX_STRING_LENGTH];8788if (!nsk_jvmti_aod_getClassName(jvmti, klass, className)) {89nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni);90return;91}9293NSK_DISPLAY2("%s: ClassLoad event was received for class '%s'\n", agentName, className);9495if (!strcmp(className, REDEFINED_CLASS_NAME)) {9697classLoadReceived = 1;9899NSK_DISPLAY1("%s: redefining class\n", agentName);100101if (!NSK_VERIFY(nsk_jvmti_aod_redefineClass(options, jvmti, klass, REDEFINED_CLASS_FILE_NAME))) {102NSK_COMPLAIN1("%s: failed to redefine class\n", agentName);103nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni);104}105}106}107108void JNICALL classPrepareHandler(109jvmtiEnv *jvmti,110JNIEnv* jni,111jthread thread,112jclass klass) {113char className[MAX_STRING_LENGTH];114115if (!nsk_jvmti_aod_getClassName(jvmti, klass, className)) {116nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni);117return;118}119120NSK_DISPLAY2("%s: ClassPrepare event received for class '%s'\n", agentName, REDEFINED_CLASS_NAME);121122if (!strcmp(className, REDEFINED_CLASS_NAME)) {123int success = 1;124125if (!classLoadReceived) {126success = 0;127NSK_COMPLAIN2("%s: expected ClassLoad event wasn't received for class '%s'\n", agentName, REDEFINED_CLASS_NAME);128}129130/*131* ClassFileLoadHook event should be received twice - when class is loaded and when class is redefined132*/133if (classFileLoadHookReceived != 2) {134success = 0;135NSK_COMPLAIN2("%s: expected ClassFileLoadHook event wasn't received for class '%s'\n", agentName, REDEFINED_CLASS_NAME);136}137138nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, success, jvmti, jni);139}140}141142void JNICALL classFileLoadHoockHandler(143jvmtiEnv * jvmti,144JNIEnv * jni,145jclass class_beeing_redefined,146jobject loader,147const char * name,148jobject protection_domain,149jint class_data_len,150const unsigned char * class_data,151jint * new_class_data_len,152unsigned char** new_class_data) {153154if (name != NULL) {155NSK_DISPLAY2("%s: ClassFileLoadHook event received for class '%s'\n", agentName, name);156if (!strcmp(name, REDEFINED_CLASS_NAME_INTERNAL)) {157classFileLoadHookReceived++;158}159} else {160NSK_DISPLAY1("%s: ClassFileLoadHook event received for class with NULL name\n", agentName);161}162}163164#ifdef STATIC_BUILD165JNIEXPORT jint JNI_OnLoad_attach002Agent00(JavaVM *jvm, char *options, void *reserved) {166return JNI_VERSION_1_8;167}168#endif169170JNIEXPORT jint JNICALL171#ifdef STATIC_BUILD172Agent_OnAttach_attach002Agent00(JavaVM *vm, char *optionsString, void *reserved)173#else174Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved)175#endif176{177jvmtiEventCallbacks eventCallbacks;178jvmtiCapabilities caps;179jvmtiEnv* jvmti = NULL;180JNIEnv* jni = NULL;181182options = (Options*) nsk_aod_createOptions(optionsString);183if (!NSK_VERIFY(options != NULL))184return JNI_ERR;185186agentName = nsk_aod_getOptionValue(options, NSK_AOD_AGENT_NAME_OPTION);187188jni = (JNIEnv*) nsk_aod_createJNIEnv(vm);189if (jni == NULL)190return NSK_FALSE;191192jvmti = nsk_jvmti_createJVMTIEnv(vm, reserved);193if (!NSK_VERIFY(jvmti != NULL))194return JNI_ERR;195196registerNativeMethods(jni);197198memset(&caps, 0, sizeof(caps));199caps.can_generate_all_class_hook_events = 1;200caps.can_redefine_classes = 1;201if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {202/*203* If VM is run with -Xshare:on agent can't get required capabilities (see 6718407)204*/205NSK_DISPLAY1("%s: warning: agent failed to get required capabilities, agent finishing\n", agentName);206207if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, agentName)))208return JNI_ERR;209210nsk_aod_agentFinished(jni, agentName, 1);211} else {212agentGotCapabilities = JNI_TRUE;213214memset(&eventCallbacks,0, sizeof(eventCallbacks));215eventCallbacks.ClassLoad = classLoadHandler;216eventCallbacks.ClassPrepare = classPrepareHandler;217eventCallbacks.ClassFileLoadHook = classFileLoadHoockHandler;218if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) {219return JNI_ERR;220}221222if (!(nsk_jvmti_aod_enableEvents(jvmti, testEvents, testEventsNumber))) {223return JNI_ERR;224}225226NSK_DISPLAY1("%s: initialization was done\n", agentName);227228if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, agentName)))229return JNI_ERR;230}231232return JNI_OK;233}234235}236237238