Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk007/classfloadhk007.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/classfloadhk007"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk007r"39#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"40#define TESTED_CLASSLOADER_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk007ClassLoader"41#define TESTED_CLASSLOADER_SIG "L" TESTED_CLASSLOADER_NAME ";"4243#define BYTECODE_FIELD_SIG "[B"44#define REDEF_BYTECODE_FIELD_NAME "redefClassBytes"4546#define CLASSLOADER_FIELD_NAME "classLoader"47#define TESTED_CLASS_FIELD_NAME "testedClass"48#define TESTED_CLASS_FIELD_SIG "Ljava/lang/Class;"4950static jobject classLoader = NULL;51static jclass testedClass = NULL;5253static jint redefClassSize = 0;54static unsigned char* redefClassBytes = NULL;5556static volatile int eventsCount = 0;5758/* ============================================================================= */5960/** Check (strictly or not) if bytecode has expected size and bytes or complain an error. */61static int checkBytecode(const char kind[], jint size, const unsigned char bytes[],62jint expectedSize, const unsigned char expectedBytes[],63int strict) {64int success = NSK_TRUE;6566NSK_DISPLAY3("Check %s bytecode: 0x%p:%d\n", kind, (void*)bytes, (int)size);67if (nsk_getVerboseMode()) {68nsk_printHexBytes(" ", 16, size, bytes);69}7071if (bytes == NULL) {72NSK_COMPLAIN2("Unexpected NULL pointer to %s bytecode in CLASS_FILE_LOAD_HOOK: 0x%p\n",73kind, (void*)bytes);74return NSK_FALSE;75}7677if (size <= 0) {78NSK_COMPLAIN2("Unexpected zero size of %s bytecode in CLASS_FILE_LOAD_HOOK: %d\n",79kind, (int)size);80return NSK_FALSE;81}8283if (strict) {84if (size != expectedSize) {85NSK_COMPLAIN3("Unexpected size of %s bytecode in CLASS_FILE_LOAD_HOOK:\n"86"# got size: %d\n"87"# expected: %d\n",88kind, (int)size, (int)expectedSize);89success = NSK_FALSE;90} else {91jint different = 0;92jint i;9394for (i = 0; i < size; i++) {95if (bytes[i] != expectedBytes[i]) {96different++;97}98}99if (different > 0) {100NSK_COMPLAIN2("Unexpected bytes in %s bytecode in CLASS_FILE_LOAD_HOOK:\n"101"# different bytes: %d\n"102"# total bytes: %d\n",103(int)different, (int)size);104success = NSK_FALSE;105}106}107108if (!success) {109NSK_COMPLAIN2("Got %s bytecode is not equal to expected bytecode: %d bytes\n",110kind, expectedSize);111if (nsk_getVerboseMode()) {112nsk_printHexBytes(" ", 16, expectedSize, expectedBytes);113}114} else {115NSK_DISPLAY1("All %s bytecode is equal to expected one\n", kind);116}117}118119return success;120}121122/** Get classfile bytecode from a static field of given class. */123static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,124const char fieldName[], const char fieldSig[],125jint* size, unsigned char* *bytes) {126127jfieldID fieldID = NULL;128jbyteArray array = NULL;129jbyte* elements;130int i;131132NSK_DISPLAY1("Find static field: %s\n", fieldName);133if (!NSK_JNI_VERIFY(jni, (fieldID =134jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {135nsk_jvmti_setFailStatus();136return NSK_FALSE;137}138NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);139140NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);141if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)142jni->GetStaticObjectField(cls, fieldID)) != NULL)) {143nsk_jvmti_setFailStatus();144return NSK_FALSE;145}146NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);147148if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {149nsk_jvmti_setFailStatus();150return NSK_FALSE;151}152NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);153154{155jboolean isCopy;156if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {157nsk_jvmti_setFailStatus();158return NSK_FALSE;159}160}161NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);162163if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {164nsk_jvmti_setFailStatus();165return NSK_FALSE;166}167NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);168169for (i = 0; i < *size; i++) {170(*bytes)[i] = (unsigned char)elements[i];171}172NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);173174NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);175NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));176NSK_DISPLAY0(" ... released\n");177178return NSK_TRUE;179}180181/** Get global reference to object from a static field of given class. */182static jobject getObject(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,183const char fieldName[], const char fieldSig[]) {184185jfieldID fieldID = NULL;186jobject obj = NULL;187188NSK_DISPLAY1("Find static field: %s\n", fieldName);189if (!NSK_JNI_VERIFY(jni, (fieldID =190jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {191nsk_jvmti_setFailStatus();192return NULL;193}194NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);195196NSK_DISPLAY1("Get object from static field: %s\n", fieldName);197if (!NSK_JNI_VERIFY(jni, (obj = jni->GetStaticObjectField(cls, fieldID)) != NULL)) {198nsk_jvmti_setFailStatus();199return NULL;200}201NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)obj);202203NSK_DISPLAY1("Make global reference to object: 0x%p\n", obj);204if (!NSK_JNI_VERIFY(jni, (obj = jni->NewGlobalRef(obj)) != NULL)) {205nsk_jvmti_setFailStatus();206return NULL;207}208NSK_DISPLAY1(" ... got global ref: 0x%p\n", (void*)obj);209210return obj;211}212213/** Redefine given class with new bytecode. */214static int redefineClass(jvmtiEnv* jvmti, jclass klass, const char className[],215jint size, unsigned char bytes[]) {216jvmtiClassDefinition classDef;217218classDef.klass = klass;219classDef.class_byte_count = size;220classDef.class_bytes = bytes;221222NSK_DISPLAY1("Redefine class: %s\n", className);223if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {224nsk_jvmti_setFailStatus();225return NSK_FALSE;226}227NSK_DISPLAY1(" ... redefined with bytecode: %d bytes\n", (int)size);228229return NSK_TRUE;230}231232/* ============================================================================= */233234/** Agent algorithm. */235static void JNICALL236agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {237NSK_DISPLAY0("Wait for debuggee to load original class\n");238if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))239return;240241/* perform testing */242{243{244jclass debugeeClass = NULL;245246NSK_DISPLAY0(">>> Obtain debuggee class\n");247NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);248if (!NSK_JNI_VERIFY(jni, (debugeeClass =249jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {250nsk_jvmti_setFailStatus();251return;252}253NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);254255NSK_DISPLAY0(">>> Obtain tested class object\n");256if (!NSK_VERIFY((testedClass = (jclass)257getObject(jvmti, jni, debugeeClass, TESTED_CLASS_FIELD_NAME,258TESTED_CLASS_FIELD_SIG)) != NULL))259return;260261NSK_DISPLAY0(">>> Obtain classloader object\n");262if (!NSK_VERIFY((classLoader =263getObject(jvmti, jni, debugeeClass, CLASSLOADER_FIELD_NAME,264TESTED_CLASSLOADER_SIG)) != NULL))265return;266267NSK_DISPLAY0(">>> Obtain redefined bytecode of tested class\n");268if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,269REDEF_BYTECODE_FIELD_NAME,270BYTECODE_FIELD_SIG,271&redefClassSize, &redefClassBytes)))272return;273}274275NSK_DISPLAY0(">>> Redefine tested class\n");276{277if (!NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,278redefClassSize, redefClassBytes)))279return;280}281282NSK_DISPLAY0(">>> Testcase #1: Redefine class and check CLASS_FILE_LOAD_HOOK event\n");283{284jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;285286NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");287if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))288return;289NSK_DISPLAY0(" ... event enabled\n");290291NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,292redefClassSize, redefClassBytes));293294NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");295if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {296NSK_DISPLAY0(" ... event disabled\n");297}298299NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");300if (eventsCount != 1) {301NSK_COMPLAIN3("Unexpected number of %s events received for tested class:\n"302"# received: %d events\n"303"# expected: %d events\n",304"CLASS_FILE_LOAD_HOOK", eventsCount, 1);305nsk_jvmti_setFailStatus();306} else {307NSK_DISPLAY1(" ... received: %d events\n", eventsCount);308}309}310311NSK_DISPLAY0(">>> Clean used data\n");312{313NSK_DISPLAY1("Delete global reference to classloader object: 0x%p\n", (void*)classLoader);314jni->DeleteGlobalRef(classLoader);315316NSK_DISPLAY1("Delete global reference to tested class object: 0x%p\n", (void*)testedClass);317jni->DeleteGlobalRef(testedClass);318319NSK_DISPLAY1("Deallocate redefined bytecode array: 0x%p\n", (void*)redefClassBytes);320if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(redefClassBytes))) {321nsk_jvmti_setFailStatus();322}323}324}325326NSK_DISPLAY0("Let debugee to finish\n");327if (!NSK_VERIFY(nsk_jvmti_resumeSync()))328return;329}330331/* ============================================================================= */332333/** Callback for CLASS_FILE_LOAD_HOOK event **/334static void JNICALL335callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,336jclass class_being_redefined,337jobject loader, const char* name, jobject protection_domain,338jint class_data_len, const unsigned char* class_data,339jint *new_class_data_len, unsigned char** new_class_data) {340341NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",342nsk_null_string(name), (void*)loader, (void*)class_being_redefined,343(void*)class_data, (int)class_data_len);344345if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {346NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);347eventsCount++;348349NSK_DISPLAY1("Check classloader: 0x%p\n", (void*)loader);350if (loader == NULL) {351NSK_COMPLAIN1("Unexpected NULL classloader in CLASS_FILE_LOAD_HOOK: 0x%p\n",352(void*)loader);353nsk_jvmti_setFailStatus();354} else if (!jni->IsSameObject(loader, classLoader)) {355NSK_COMPLAIN2("Unexpected classloader in CLASS_FILE_LOAD_HOOK:\n"356"# got classloder: 0x%p\n"357"# expected same as: 0x%p\n",358(void*)loader, (void*)classLoader);359nsk_jvmti_setFailStatus();360}361362NSK_DISPLAY1("Check class_being_redefined: 0x%p\n", (void*)class_being_redefined);363if (class_being_redefined == NULL) {364NSK_COMPLAIN1("Unexpected NULL class_being_redefined in CLASS_FILE_LOAD_HOOK: 0x%p\n",365(void*)class_being_redefined);366nsk_jvmti_setFailStatus();367} else if (!jni->IsSameObject(class_being_redefined, testedClass)) {368NSK_COMPLAIN2("Unexpected class_being_redefined in CLASS_FILE_LOAD_HOOK:\n"369"# got class: 0x%p\n"370"# expected same as: 0x%p\n",371(void*)class_being_redefined, (void*)testedClass);372nsk_jvmti_setFailStatus();373}374375if (!checkBytecode("redefined", class_data_len, class_data,376redefClassSize, redefClassBytes, NSK_TRUE)) {377nsk_jvmti_setFailStatus();378}379}380}381382/* ============================================================================= */383384/** Agent library initialization. */385#ifdef STATIC_BUILD386JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {387return Agent_Initialize(jvm, options, reserved);388}389JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {390return Agent_Initialize(jvm, options, reserved);391}392JNIEXPORT jint JNI_OnLoad_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {393return JNI_VERSION_1_8;394}395#endif396jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {397jvmtiEnv* jvmti = NULL;398399/* init framework and parse options */400if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))401return JNI_ERR;402403timeout = nsk_jvmti_getWaitTime() * 60 * 1000;404405/* create JVMTI environment */406if (!NSK_VERIFY((jvmti =407nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))408return JNI_ERR;409410NSK_DISPLAY1("Add required capabilities: %s\n", "can_generate_eraly_class_hook_events, can_redefine_classes");411{412jvmtiCapabilities caps;413414memset(&caps, 0, sizeof(caps));415caps.can_generate_all_class_hook_events = 1;416caps.can_redefine_classes = 1;417if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {418return JNI_ERR;419}420}421NSK_DISPLAY0(" ... added\n");422423NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");424{425jvmtiEventCallbacks callbacks;426jint size = (jint)sizeof(callbacks);427428memset(&callbacks, 0, sizeof(callbacks));429callbacks.ClassFileLoadHook = callbackClassFileLoadHook;430if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {431return JNI_ERR;432}433}434NSK_DISPLAY0(" ... set\n");435436/* register agent proc and arg */437if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))438return JNI_ERR;439440return JNI_OK;441}442443/* ============================================================================= */444445}446447448