Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk006/classfloadhk006.cpp
40955 views
/*1* Copyright (c) 2003, 2018, 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 <string.h>24#include "jvmti.h"25#include "agent_common.h"26#include "jni_tools.h"27#include "jvmti_tools.h"2829extern "C" {3031/* ============================================================================= */3233/* scaffold objects */34static jlong timeout = 0;3536/* constant names */37#define DEBUGEE_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk006"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk006r"39#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"4041#define BYTECODE_FIELD_SIG "[B"42#define REDEF_BYTECODE_FIELD_NAME "redefClassBytes"4344#define TESTED_CLASS_FIELD_NAME "testedClass"45#define TESTED_CLASS_FIELD_SIG "Ljava/lang/Class;"4647static jclass testedClass = NULL;4849static jint redefClassSize = 0;50static unsigned char* redefClassBytes = NULL;5152static volatile int eventsCount = 0;5354/* ============================================================================= */5556/** Check (strictly or not) if bytecode has expected size and bytes or complain an error. */57static int checkBytecode(const char kind[], jint size, const unsigned char bytes[],58jint expectedSize, const unsigned char expectedBytes[],59int strict) {60int success = NSK_TRUE;6162NSK_DISPLAY3("Check %s bytecode: 0x%p:%d\n", kind, (void*)bytes, (int)size);63if (nsk_getVerboseMode()) {64nsk_printHexBytes(" ", 16, size, bytes);65}6667if (bytes == NULL) {68NSK_COMPLAIN2("Unexpected NULL pointer to %s bytecode in CLASS_FILE_LOAD_HOOK: 0x%p\n",69kind, (void*)bytes);70return NSK_FALSE;71}7273if (size <= 0) {74NSK_COMPLAIN2("Unexpected zero size of %s bytecode in CLASS_FILE_LOAD_HOOK: %d\n",75kind, (int)size);76return NSK_FALSE;77}7879if (strict) {80if (size != expectedSize) {81NSK_COMPLAIN3("Unexpected size of %s bytecode in CLASS_FILE_LOAD_HOOK:\n"82"# got size: %d\n"83"# expected: %d\n",84kind, (int)size, (int)expectedSize);85success = NSK_FALSE;86} else {87jint different = 0;88jint i;8990for (i = 0; i < size; i++) {91if (bytes[i] != expectedBytes[i]) {92different++;93}94}95if (different > 0) {96NSK_COMPLAIN2("Unexpected bytes in %s bytecode in CLASS_FILE_LOAD_HOOK:\n"97"# different bytes: %d\n"98"# total bytes: %d\n",99(int)different, (int)size);100success = NSK_FALSE;101}102}103104if (!success) {105NSK_COMPLAIN2("Got %s bytecode is not equal to expected bytecode: %d bytes\n",106kind, expectedSize);107if (nsk_getVerboseMode()) {108nsk_printHexBytes(" ", 16, expectedSize, expectedBytes);109}110} else {111NSK_DISPLAY1("All %s bytecode is equal to expected one\n", kind);112}113}114115return success;116}117118/** Get classfile bytecode from a static field of given class. */119static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,120const char fieldName[], const char fieldSig[],121jint* size, unsigned char* *bytes) {122123jfieldID fieldID = NULL;124jbyteArray array = NULL;125jbyte* elements;126int i;127128NSK_DISPLAY1("Find static field: %s\n", fieldName);129if (!NSK_JNI_VERIFY(jni, (fieldID =130jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {131nsk_jvmti_setFailStatus();132return NSK_FALSE;133}134NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);135136NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);137if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)138jni->GetStaticObjectField(cls, fieldID)) != NULL)) {139nsk_jvmti_setFailStatus();140return NSK_FALSE;141}142NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);143144if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {145nsk_jvmti_setFailStatus();146return NSK_FALSE;147}148NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);149150{151jboolean isCopy;152if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {153nsk_jvmti_setFailStatus();154return NSK_FALSE;155}156}157NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);158159if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {160nsk_jvmti_setFailStatus();161return NSK_FALSE;162}163NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);164165for (i = 0; i < *size; i++) {166(*bytes)[i] = (unsigned char)elements[i];167}168NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);169170NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);171NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));172NSK_DISPLAY0(" ... released\n");173174return NSK_TRUE;175}176177/** Get global reference to object from a static field of given class. */178static jobject getObject(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,179const char fieldName[], const char fieldSig[]) {180181jfieldID fieldID = NULL;182jobject obj = NULL;183184NSK_DISPLAY1("Find static field: %s\n", fieldName);185if (!NSK_JNI_VERIFY(jni, (fieldID =186jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {187nsk_jvmti_setFailStatus();188return NULL;189}190NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);191192NSK_DISPLAY1("Get object from static field: %s\n", fieldName);193if (!NSK_JNI_VERIFY(jni, (obj = jni->GetStaticObjectField(cls, fieldID)) != NULL)) {194nsk_jvmti_setFailStatus();195return NULL;196}197NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)obj);198199NSK_DISPLAY1("Make global reference to object: 0x%p\n", obj);200if (!NSK_JNI_VERIFY(jni, (obj = jni->NewGlobalRef(obj)) != NULL)) {201nsk_jvmti_setFailStatus();202return NULL;203}204NSK_DISPLAY1(" ... got global ref: 0x%p\n", (void*)obj);205206return obj;207}208209/** Redefine given class with new bytecode. */210static int redefineClass(jvmtiEnv* jvmti, jclass klass, const char className[],211jint size, unsigned char bytes[]) {212jvmtiClassDefinition classDef;213214classDef.klass = klass;215classDef.class_byte_count = size;216classDef.class_bytes = bytes;217218NSK_DISPLAY1("Redefine class: %s\n", className);219if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {220nsk_jvmti_setFailStatus();221return NSK_FALSE;222}223NSK_DISPLAY1(" ... redefined with bytecode: %d bytes\n", (int)size);224225return NSK_TRUE;226}227228/* ============================================================================= */229230/** Agent algorithm. */231static void JNICALL232agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {233NSK_DISPLAY0("Wait for debuggee to load original class\n");234if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))235return;236237/* perform testing */238{239{240jclass debugeeClass = NULL;241242NSK_DISPLAY0(">>> Obtain debuggee class\n");243NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);244if (!NSK_JNI_VERIFY(jni, (debugeeClass =245jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {246nsk_jvmti_setFailStatus();247return;248}249NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);250251NSK_DISPLAY0(">>> Obtain tested class object\n");252if (!NSK_VERIFY((testedClass = (jclass)253getObject(jvmti, jni, debugeeClass, TESTED_CLASS_FIELD_NAME,254TESTED_CLASS_FIELD_SIG)) != NULL))255return;256257NSK_DISPLAY0(">>> Obtain redefined bytecode of tested class\n");258if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,259REDEF_BYTECODE_FIELD_NAME,260BYTECODE_FIELD_SIG,261&redefClassSize, &redefClassBytes)))262return;263}264265NSK_DISPLAY0(">>> Redefine tested class\n");266{267if (!NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,268redefClassSize, redefClassBytes)))269return;270}271272NSK_DISPLAY0(">>> Testcase #1: Redefine class and check CLASS_FILE_LOAD_HOOK event\n");273{274jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;275276NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");277if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))278return;279NSK_DISPLAY0(" ... event enabled\n");280281NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,282redefClassSize, redefClassBytes));283284NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");285if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {286NSK_DISPLAY0(" ... event disabled\n");287}288289NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");290if (eventsCount != 1) {291NSK_COMPLAIN3("Unexpected number of %s events received for tested class:\n"292"# received: %d events\n"293"# expected: %d events\n",294"CLASS_FILE_LOAD_HOOK", eventsCount, 1);295nsk_jvmti_setFailStatus();296} else {297NSK_DISPLAY1(" ... received: %d events\n", eventsCount);298}299}300301NSK_DISPLAY0(">>> Clean used data\n");302{303NSK_DISPLAY1("Delete global reference to tested class object: 0x%p\n", (void*)testedClass);304jni->DeleteGlobalRef(testedClass);305306NSK_DISPLAY1("Deallocate redefined bytecode array: 0x%p\n", (void*)redefClassBytes);307if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(redefClassBytes))) {308nsk_jvmti_setFailStatus();309}310}311}312313NSK_DISPLAY0("Let debugee to finish\n");314if (!NSK_VERIFY(nsk_jvmti_resumeSync()))315return;316}317318/* ============================================================================= */319320/** Callback for CLASS_FILE_LOAD_HOOK event **/321static void JNICALL322callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,323jclass class_being_redefined,324jobject loader, const char* name, jobject protection_domain,325jint class_data_len, const unsigned char* class_data,326jint *new_class_data_len, unsigned char** new_class_data) {327328NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",329nsk_null_string(name), (void*)loader, (void*)class_being_redefined,330(void*)class_data, (int)class_data_len);331332if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {333NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);334eventsCount++;335336NSK_DISPLAY1("Check class_being_redefined: 0x%p\n", (void*)class_being_redefined);337if (class_being_redefined == NULL) {338NSK_COMPLAIN1("Unexpected NULL class_being_redefined in CLASS_FILE_LOAD_HOOK: 0x%p\n",339(void*)class_being_redefined);340nsk_jvmti_setFailStatus();341} else if (!jni->IsSameObject(class_being_redefined, testedClass)) {342NSK_COMPLAIN2("Unexpected class_being_redefined in CLASS_FILE_LOAD_HOOK:\n"343"# got class: 0x%p\n"344"# expected same as: 0x%p\n",345(void*)class_being_redefined, (void*)testedClass);346nsk_jvmti_setFailStatus();347}348349if (!checkBytecode("redefined", class_data_len, class_data,350redefClassSize, redefClassBytes, NSK_TRUE)) {351nsk_jvmti_setFailStatus();352}353}354}355356/* ============================================================================= */357358/** Agent library initialization. */359#ifdef STATIC_BUILD360JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk006(JavaVM *jvm, char *options, void *reserved) {361return Agent_Initialize(jvm, options, reserved);362}363JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk006(JavaVM *jvm, char *options, void *reserved) {364return Agent_Initialize(jvm, options, reserved);365}366JNIEXPORT jint JNI_OnLoad_classfloadhk006(JavaVM *jvm, char *options, void *reserved) {367return JNI_VERSION_1_8;368}369#endif370jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {371jvmtiEnv* jvmti = NULL;372373/* init framework and parse options */374if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))375return JNI_ERR;376377timeout = nsk_jvmti_getWaitTime() * 60 * 1000;378379/* create JVMTI environment */380if (!NSK_VERIFY((jvmti =381nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))382return JNI_ERR;383384NSK_DISPLAY1("Add required capabilities: %s\n", "can_generate_eraly_class_hook_events, can_redefine_classes");385{386jvmtiCapabilities caps;387388memset(&caps, 0, sizeof(caps));389caps.can_generate_all_class_hook_events = 1;390caps.can_redefine_classes = 1;391if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {392return JNI_ERR;393}394}395NSK_DISPLAY0(" ... added\n");396397NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");398{399jvmtiEventCallbacks callbacks;400jint size = (jint)sizeof(callbacks);401402memset(&callbacks, 0, sizeof(callbacks));403callbacks.ClassFileLoadHook = callbackClassFileLoadHook;404if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {405return JNI_ERR;406}407}408NSK_DISPLAY0(" ... set\n");409410/* register agent proc and arg */411if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))412return JNI_ERR;413414return JNI_OK;415}416417/* ============================================================================= */418419}420421422