Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk009/classfloadhk009.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/classfloadhk009"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk009r"39#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"4041#define BYTECODE_FIELD_SIG "[B"42#define REDEF_BYTECODE_FIELD_NAME "redefClassBytes"43#define NEW_BYTECODE_FIELD_NAME "newClassBytes"4445#define TESTED_CLASS_FIELD_NAME "testedClass"46#define TESTED_CLASS_FIELD_SIG "Ljava/lang/Class;"4748static jclass testedClass = NULL;4950static jint redefClassSize = 0;51static unsigned char* redefClassBytes = NULL;5253static jint newClassSize = 0;54static unsigned char* newClassBytes = NULL;5556static volatile int eventsCount = 0;5758/* ============================================================================= */5960/** Get classfile bytecode from a static field of given class. */61static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,62const char fieldName[], const char fieldSig[],63jint* size, unsigned char* *bytes) {6465jfieldID fieldID = NULL;66jbyteArray array = NULL;67jbyte* elements;68int i;6970NSK_DISPLAY1("Find static field: %s\n", fieldName);71if (!NSK_JNI_VERIFY(jni, (fieldID =72jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {73nsk_jvmti_setFailStatus();74return NSK_FALSE;75}76NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);7778NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);79if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)80jni->GetStaticObjectField(cls, fieldID)) != NULL)) {81nsk_jvmti_setFailStatus();82return NSK_FALSE;83}84NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);8586if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {87nsk_jvmti_setFailStatus();88return NSK_FALSE;89}90NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);9192{93jboolean isCopy;94if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {95nsk_jvmti_setFailStatus();96return NSK_FALSE;97}98}99NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);100101if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {102nsk_jvmti_setFailStatus();103return NSK_FALSE;104}105NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);106107for (i = 0; i < *size; i++) {108(*bytes)[i] = (unsigned char)elements[i];109}110NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);111112NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);113NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));114NSK_DISPLAY0(" ... released\n");115116return NSK_TRUE;117}118119/** Get global reference to object from a static field of given class. */120static jobject getObject(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,121const char fieldName[], const char fieldSig[]) {122123jfieldID fieldID = NULL;124jobject obj = NULL;125126NSK_DISPLAY1("Find static field: %s\n", fieldName);127if (!NSK_JNI_VERIFY(jni, (fieldID =128jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {129nsk_jvmti_setFailStatus();130return NULL;131}132NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);133134NSK_DISPLAY1("Get object from static field: %s\n", fieldName);135if (!NSK_JNI_VERIFY(jni, (obj = jni->GetStaticObjectField(cls, fieldID)) != NULL)) {136nsk_jvmti_setFailStatus();137return NULL;138}139NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)obj);140141NSK_DISPLAY1("Make global reference to object: 0x%p\n", obj);142if (!NSK_JNI_VERIFY(jni, (obj = jni->NewGlobalRef(obj)) != NULL)) {143nsk_jvmti_setFailStatus();144return NULL;145}146NSK_DISPLAY1(" ... got global ref: 0x%p\n", (void*)obj);147148return obj;149}150151/** Redefine given class with new bytecode. */152static int redefineClass(jvmtiEnv* jvmti, jclass klass, const char className[],153jint size, unsigned char bytes[]) {154jvmtiClassDefinition classDef;155156classDef.klass = klass;157classDef.class_byte_count = size;158classDef.class_bytes = bytes;159160NSK_DISPLAY1("Redefine class: %s\n", className);161if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {162nsk_jvmti_setFailStatus();163return NSK_FALSE;164}165NSK_DISPLAY1(" ... redefined with bytecode: %d bytes\n", (int)size);166167return NSK_TRUE;168}169170/* ============================================================================= */171172/** Agent algorithm. */173static void JNICALL174agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {175NSK_DISPLAY0("Wait for debuggee to load original class\n");176if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))177return;178179/* perform testing */180{181{182jclass debugeeClass = NULL;183184NSK_DISPLAY0(">>> Obtain debuggee class\n");185NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);186if (!NSK_JNI_VERIFY(jni, (debugeeClass =187jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {188nsk_jvmti_setFailStatus();189return;190}191NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);192193NSK_DISPLAY0(">>> Obtain tested class object\n");194if (!NSK_VERIFY((testedClass = (jclass)195getObject(jvmti, jni, debugeeClass, TESTED_CLASS_FIELD_NAME,196TESTED_CLASS_FIELD_SIG)) != NULL))197return;198199NSK_DISPLAY0(">>> Obtain redefined bytecode of tested class\n");200if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,201REDEF_BYTECODE_FIELD_NAME,202BYTECODE_FIELD_SIG,203&redefClassSize, &redefClassBytes)))204return;205206NSK_DISPLAY0(">>> Obtain new instrumented bytecode of tested class\n");207if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,208NEW_BYTECODE_FIELD_NAME,209BYTECODE_FIELD_SIG,210&newClassSize, &newClassBytes)))211return;212}213214NSK_DISPLAY0(">>> Redefine tested class\n");215{216if (!NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,217redefClassSize, redefClassBytes)))218return;219}220221NSK_DISPLAY0(">>> Testcase #1: Redefine class and check CLASS_FILE_LOAD_HOOK event\n");222{223jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;224225NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");226if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))227return;228NSK_DISPLAY0(" ... event enabled\n");229230NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,231redefClassSize, redefClassBytes));232233NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");234if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {235NSK_DISPLAY0(" ... event disabled\n");236}237238NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");239if (eventsCount != 1) {240NSK_COMPLAIN3("Unexpected number of %s events received for tested class:\n"241"# received: %d events\n"242"# expected: %d events\n",243"CLASS_FILE_LOAD_HOOK", eventsCount, 1);244nsk_jvmti_setFailStatus();245} else {246NSK_DISPLAY1(" ... received: %d events\n", eventsCount);247}248}249250NSK_DISPLAY0(">>> Clean used data\n");251{252NSK_DISPLAY1("Delete global reference to tested class object: 0x%p\n", (void*)testedClass);253jni->DeleteGlobalRef(testedClass);254255NSK_DISPLAY1("Deallocate redefined bytecode array: 0x%p\n", (void*)redefClassBytes);256if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(redefClassBytes))) {257nsk_jvmti_setFailStatus();258}259}260}261262NSK_DISPLAY0("Let debugee to finish\n");263if (!NSK_VERIFY(nsk_jvmti_resumeSync()))264return;265}266267/* ============================================================================= */268269/** Callback for CLASS_FILE_LOAD_HOOK event **/270static void JNICALL271callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,272jclass class_being_redefined,273jobject loader, const char* name, jobject protection_domain,274jint class_data_len, const unsigned char* class_data,275jint *new_class_data_len, unsigned char** new_class_data) {276277NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",278nsk_null_string(name), (void*)loader, (void*)class_being_redefined,279(void*)class_data, (int)class_data_len);280281if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {282NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);283eventsCount++;284285NSK_DISPLAY2("Received redefined bytecode of redefined class: 0x%p:%d\n",286(void*)class_data, (int)class_data_len);287if (nsk_getVerboseMode()) {288nsk_printHexBytes(" ", 16, class_data_len, class_data);289}290291NSK_DISPLAY1("Check pointer to new_class_data_len: 0x%p\n", (void*)new_class_data_len);292if (new_class_data_len == NULL) {293NSK_COMPLAIN1("NULL new_class_data_len pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",294(void*)new_class_data_len);295nsk_jvmti_setFailStatus();296}297298NSK_DISPLAY1("Check pointer to new_class_data: 0x%p\n", (void*)new_class_data);299if (new_class_data == NULL) {300NSK_COMPLAIN1("NULL new_class_data pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",301(void*)new_class_data);302nsk_jvmti_setFailStatus();303}304305if (new_class_data_len != NULL && new_class_data != NULL) {306NSK_DISPLAY2("Replace with new instrumented bytecode: 0x%p:%d\n",307(void*)newClassBytes, (int)newClassSize);308if (nsk_getVerboseMode()) {309nsk_printHexBytes(" ", 16, newClassSize, newClassBytes);310}311312*new_class_data_len = newClassSize;313*new_class_data = newClassBytes;314}315}316}317318/* ============================================================================= */319320/** Agent library initialization. */321#ifdef STATIC_BUILD322JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk009(JavaVM *jvm, char *options, void *reserved) {323return Agent_Initialize(jvm, options, reserved);324}325JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk009(JavaVM *jvm, char *options, void *reserved) {326return Agent_Initialize(jvm, options, reserved);327}328JNIEXPORT jint JNI_OnLoad_classfloadhk009(JavaVM *jvm, char *options, void *reserved) {329return JNI_VERSION_1_8;330}331#endif332jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {333jvmtiEnv* jvmti = NULL;334335/* init framework and parse options */336if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))337return JNI_ERR;338339timeout = nsk_jvmti_getWaitTime() * 60 * 1000;340341/* create JVMTI environment */342if (!NSK_VERIFY((jvmti =343nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))344return JNI_ERR;345346NSK_DISPLAY1("Add required capabilities: %s\n", "can_generate_eraly_class_hook_events, can_redefine_classes");347{348jvmtiCapabilities caps;349350memset(&caps, 0, sizeof(caps));351caps.can_generate_all_class_hook_events = 1;352caps.can_redefine_classes = 1;353if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {354return JNI_ERR;355}356}357NSK_DISPLAY0(" ... added\n");358359NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");360{361jvmtiEventCallbacks callbacks;362jint size = (jint)sizeof(callbacks);363364memset(&callbacks, 0, sizeof(callbacks));365callbacks.ClassFileLoadHook = callbackClassFileLoadHook;366if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {367return JNI_ERR;368}369}370NSK_DISPLAY0(" ... set\n");371372/* register agent proc and arg */373if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))374return JNI_ERR;375376return JNI_OK;377}378379/* ============================================================================= */380381}382383384