Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk004/classfloadhk004.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/classfloadhk004"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk004r"39#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"4041#define BYTECODE_FIELD_SIG "[B"42#define NEW_BYTECODE_FIELD_NAME "newClassBytes"4344static jint newClassSize = 0;45static unsigned char* newClassBytes = NULL;4647static volatile int eventsCount = 0;4849/* ============================================================================= */5051/** Get classfile bytecode from a static field of given class. */52static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,53const char fieldName[], const char fieldSig[],54jint* size, unsigned char* *bytes) {5556jfieldID fieldID = NULL;57jbyteArray array = NULL;58jbyte* elements;59int i;6061NSK_DISPLAY1("Find static field: %s\n", fieldName);62if (!NSK_JNI_VERIFY(jni, (fieldID =63jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {64nsk_jvmti_setFailStatus();65return NSK_FALSE;66}67NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);6869NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);70if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)71jni->GetStaticObjectField(cls, fieldID)) != NULL)) {72nsk_jvmti_setFailStatus();73return NSK_FALSE;74}75NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);7677if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {78nsk_jvmti_setFailStatus();79return NSK_FALSE;80}81NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);8283{84jboolean isCopy;85if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {86nsk_jvmti_setFailStatus();87return NSK_FALSE;88}89}90NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);9192if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {93nsk_jvmti_setFailStatus();94return NSK_FALSE;95}96NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);9798for (i = 0; i < *size; i++) {99(*bytes)[i] = (unsigned char)elements[i];100}101NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);102103NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);104NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));105NSK_DISPLAY0(" ... released\n");106107return NSK_TRUE;108}109110/* ============================================================================= */111112/** Agent algorithm. */113static void JNICALL114agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {115NSK_DISPLAY0("Wait for debuggee to become ready\n");116if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))117return;118119/* perform testing */120{121NSK_DISPLAY0(">>> Obtain classloader and instrumented bytecode of tested class\n");122{123jclass debugeeClass = NULL;124125NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);126if (!NSK_JNI_VERIFY(jni, (debugeeClass =127jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {128nsk_jvmti_setFailStatus();129return;130}131NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);132133if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,134NEW_BYTECODE_FIELD_NAME,135BYTECODE_FIELD_SIG,136&newClassSize, &newClassBytes)))137return;138}139140NSK_DISPLAY0(">>> Testcase #1: Load tested class and replace bytecode in CLASS_FILE_LOAD_HOOK event\n");141{142jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;143144NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");145if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))146return;147NSK_DISPLAY0(" ... event enabled\n");148149NSK_DISPLAY0("Let debugee to load tested class\n");150if (!NSK_VERIFY(nsk_jvmti_resumeSync()))151return;152NSK_DISPLAY0("Wait for tested class to be loaded\n");153if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))154return;155156NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");157if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {158NSK_DISPLAY0(" ... event disabled\n");159}160161NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");162if (eventsCount != 1) {163NSK_COMPLAIN3("Unexpected number of %s events for tested class:\n"164"# got events: %d\n"165"# expected: %d\n",166"CLASS_FILE_LOAD_HOOK",167eventsCount, 1);168nsk_jvmti_setFailStatus();169} else {170NSK_DISPLAY1(" ... received: %d events\n", eventsCount);171}172}173174NSK_DISPLAY0(">>> Clean used data\n");175{176}177}178179NSK_DISPLAY0("Let debugee to finish\n");180if (!NSK_VERIFY(nsk_jvmti_resumeSync()))181return;182}183184/* ============================================================================= */185186/** Callback for CLASS_FILE_LOAD_HOOK event **/187static void JNICALL188callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,189jclass class_being_redefined,190jobject loader, const char* name, jobject protection_domain,191jint class_data_len, const unsigned char* class_data,192jint *new_class_data_len, unsigned char** new_class_data) {193194NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",195nsk_null_string(name), (void*)loader, (void*)class_being_redefined,196(void*)class_data, (int)class_data_len);197198if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {199NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);200eventsCount++;201202NSK_DISPLAY2("Received bytecode of loaded class: 0x%p:%d\n",203(void*)class_data, (int)class_data_len);204if (nsk_getVerboseMode()) {205nsk_printHexBytes(" ", 16, class_data_len, class_data);206}207208NSK_DISPLAY1("Check pointer to new_class_data_len: 0x%p\n", (void*)new_class_data_len);209if (new_class_data_len == NULL) {210NSK_COMPLAIN1("NULL new_class_data_len pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",211(void*)new_class_data_len);212nsk_jvmti_setFailStatus();213}214215NSK_DISPLAY1("Check pointer to new_class_data: 0x%p\n", (void*)new_class_data);216if (new_class_data == NULL) {217NSK_COMPLAIN1("NULL new_class_data pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",218(void*)new_class_data);219nsk_jvmti_setFailStatus();220}221222if (new_class_data_len != NULL && new_class_data != NULL) {223NSK_DISPLAY2("Replace with new bytecode: 0x%p:%d\n",224(void*)newClassBytes, (int)newClassSize);225if (nsk_getVerboseMode()) {226nsk_printHexBytes(" ", 16, newClassSize, newClassBytes);227}228229*new_class_data_len = newClassSize;230*new_class_data = newClassBytes;231}232}233}234235/* ============================================================================= */236237/** Agent library initialization. */238#ifdef STATIC_BUILD239JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk004(JavaVM *jvm, char *options, void *reserved) {240return Agent_Initialize(jvm, options, reserved);241}242JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk004(JavaVM *jvm, char *options, void *reserved) {243return Agent_Initialize(jvm, options, reserved);244}245JNIEXPORT jint JNI_OnLoad_classfloadhk004(JavaVM *jvm, char *options, void *reserved) {246return JNI_VERSION_1_8;247}248#endif249jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {250jvmtiEnv* jvmti = NULL;251252/* init framework and parse options */253if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))254return JNI_ERR;255256timeout = nsk_jvmti_getWaitTime() * 60 * 1000;257258/* create JVMTI environment */259if (!NSK_VERIFY((jvmti =260nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))261return JNI_ERR;262263NSK_DISPLAY1("Add required capability: %s\n", "can_generate_eraly_class_hook_events");264{265jvmtiCapabilities caps;266267memset(&caps, 0, sizeof(caps));268caps.can_generate_all_class_hook_events = 1;269if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {270return JNI_ERR;271}272}273NSK_DISPLAY0(" ... added\n");274275NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");276{277jvmtiEventCallbacks callbacks;278jint size = (jint)sizeof(callbacks);279280memset(&callbacks, 0, sizeof(callbacks));281callbacks.ClassFileLoadHook = callbackClassFileLoadHook;282if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {283return JNI_ERR;284}285}286NSK_DISPLAY0(" ... set\n");287288/* register agent proc and arg */289if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))290return JNI_ERR;291292return JNI_OK;293}294295/* ============================================================================= */296297}298299300