Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk005/classfloadhk005.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/classfloadhk005"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk005r"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/** Check (strictly or not) if bytecode has expected size and bytes or complain an error. */52static int checkBytecode(const char kind[], jint size, const unsigned char bytes[],53jint expectedSize, const unsigned char expectedBytes[],54int strict) {55int success = NSK_TRUE;5657NSK_DISPLAY3("Check %s bytecode: 0x%p:%d\n", kind, (void*)bytes, (int)size);58if (nsk_getVerboseMode()) {59nsk_printHexBytes(" ", 16, size, bytes);60}6162if (bytes == NULL) {63NSK_COMPLAIN2("Unexpected NULL pointer to %s bytecode in CLASS_FILE_LOAD_HOOK: 0x%p\n",64kind, (void*)bytes);65return NSK_FALSE;66}6768if (size <= 0) {69NSK_COMPLAIN2("Unexpected zero size of %s bytecode in CLASS_FILE_LOAD_HOOK: %d\n",70kind, (int)size);71return NSK_FALSE;72}7374if (strict) {75if (size != expectedSize) {76NSK_COMPLAIN3("Unexpected size of %s bytecode in CLASS_FILE_LOAD_HOOK:\n"77"# got size: %d\n"78"# expected: %d\n",79kind, (int)size, (int)expectedSize);80success = NSK_FALSE;81} else {82jint different = 0;83jint i;8485for (i = 0; i < size; i++) {86if (bytes[i] != expectedBytes[i]) {87different++;88}89}90if (different > 0) {91NSK_COMPLAIN2("Unexpected bytes in %s bytecode in CLASS_FILE_LOAD_HOOK:\n"92"# different bytes: %d\n"93"# total bytes: %d\n",94(int)different, (int)size);95success = NSK_FALSE;96}97}9899if (!success) {100NSK_COMPLAIN2("Got %s bytecode is not equal to expected bytecode: %d bytes\n",101kind, expectedSize);102if (nsk_getVerboseMode()) {103nsk_printHexBytes(" ", 16, expectedSize, expectedBytes);104}105} else {106NSK_DISPLAY1("All %s bytecode is equal to expected one\n", kind);107}108}109110return success;111}112113/** Get classfile bytecode from a static field of given class. */114static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,115const char fieldName[], const char fieldSig[],116jint* size, unsigned char* *bytes) {117118jfieldID fieldID = NULL;119jbyteArray array = NULL;120jbyte* elements;121int i;122123NSK_DISPLAY1("Find static field: %s\n", fieldName);124if (!NSK_JNI_VERIFY(jni, (fieldID =125jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {126nsk_jvmti_setFailStatus();127return NSK_FALSE;128}129NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);130131NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);132if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)133jni->GetStaticObjectField(cls, fieldID)) != NULL)) {134nsk_jvmti_setFailStatus();135return NSK_FALSE;136}137NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);138139if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {140nsk_jvmti_setFailStatus();141return NSK_FALSE;142}143NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);144145{146jboolean isCopy;147if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {148nsk_jvmti_setFailStatus();149return NSK_FALSE;150}151}152NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);153154if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {155nsk_jvmti_setFailStatus();156return NSK_FALSE;157}158NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);159160for (i = 0; i < *size; i++) {161(*bytes)[i] = (unsigned char)elements[i];162}163NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);164165NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);166NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));167NSK_DISPLAY0(" ... released\n");168169return NSK_TRUE;170}171172/* ============================================================================= */173174/** Agent algorithm. */175static void JNICALL176agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {177NSK_DISPLAY0("Wait for debuggee to become ready\n");178if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))179return;180181/* perform testing */182{183NSK_DISPLAY0(">>> Obtain classloader and instrumented bytecode of tested class\n");184{185jclass debugeeClass = NULL;186187NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);188if (!NSK_JNI_VERIFY(jni, (debugeeClass =189jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {190nsk_jvmti_setFailStatus();191return;192}193NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);194195if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,196NEW_BYTECODE_FIELD_NAME,197BYTECODE_FIELD_SIG,198&newClassSize, &newClassBytes)))199return;200}201202NSK_DISPLAY0(">>> Testcase #1: Load tested class and replace bytecode in CLASS_FILE_LOAD_HOOK event\n");203{204jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;205206NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");207if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))208return;209NSK_DISPLAY0(" ... event enabled\n");210211NSK_DISPLAY0("Let debugee to load tested class\n");212if (!NSK_VERIFY(nsk_jvmti_resumeSync()))213return;214NSK_DISPLAY0("Wait for tested class to be loaded\n");215if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))216return;217218NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");219if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {220NSK_DISPLAY0(" ... event disabled\n");221}222223NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");224if (eventsCount != 1) {225NSK_COMPLAIN3("Unexpected number of %s events for tested class:\n"226"# got events: %d\n"227"# expected: %d\n",228"CLASS_FILE_LOAD_HOOK",229eventsCount, 1);230nsk_jvmti_setFailStatus();231} else {232NSK_DISPLAY1(" ... received: %d events\n", eventsCount);233}234}235236NSK_DISPLAY0(">>> Clean used data\n");237{238}239}240241NSK_DISPLAY0("Let debugee to finish\n");242if (!NSK_VERIFY(nsk_jvmti_resumeSync()))243return;244}245246/* ============================================================================= */247248/** Callback for CLASS_FILE_LOAD_HOOK event **/249static void JNICALL250callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,251jclass class_being_redefined,252jobject loader, const char* name, jobject protection_domain,253jint class_data_len, const unsigned char* class_data,254jint *new_class_data_len, unsigned char** new_class_data) {255256NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",257nsk_null_string(name), (void*)loader, (void*)class_being_redefined,258(void*)class_data, (int)class_data_len);259260if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {261NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);262eventsCount++;263264NSK_DISPLAY2("Received original bytecode of tested class: 0x%p:%d\n",265(void*)class_data, (int)class_data_len);266if (nsk_getVerboseMode()) {267nsk_printHexBytes(" ", 16, class_data_len, class_data);268}269270NSK_DISPLAY1("Check pointer to new_class_data_len: 0x%p\n", (void*)new_class_data_len);271if (new_class_data_len == NULL) {272NSK_COMPLAIN1("NULL new_class_data_len pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",273(void*)new_class_data_len);274nsk_jvmti_setFailStatus();275}276277NSK_DISPLAY1("Check pointer to new_class_data: 0x%p\n", (void*)new_class_data);278if (new_class_data == NULL) {279NSK_COMPLAIN1("NULL new_class_data pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n",280(void*)new_class_data);281nsk_jvmti_setFailStatus();282}283284if (new_class_data_len != NULL && new_class_data != NULL) {285NSK_DISPLAY2("Replace with instrumented bytecode: 0x%p:%d\n",286(void*)newClassBytes, (int)newClassSize);287if (nsk_getVerboseMode()) {288nsk_printHexBytes(" ", 16, newClassSize, newClassBytes);289}290291*new_class_data_len = newClassSize;292*new_class_data = newClassBytes;293}294}295}296297/* ============================================================================= */298299/** Agent library initialization. */300#ifdef STATIC_BUILD301JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk005(JavaVM *jvm, char *options, void *reserved) {302return Agent_Initialize(jvm, options, reserved);303}304JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk005(JavaVM *jvm, char *options, void *reserved) {305return Agent_Initialize(jvm, options, reserved);306}307JNIEXPORT jint JNI_OnLoad_classfloadhk005(JavaVM *jvm, char *options, void *reserved) {308return JNI_VERSION_1_8;309}310#endif311jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {312jvmtiEnv* jvmti = NULL;313314/* init framework and parse options */315if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))316return JNI_ERR;317318timeout = nsk_jvmti_getWaitTime() * 60 * 1000;319320/* create JVMTI environment */321if (!NSK_VERIFY((jvmti =322nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))323return JNI_ERR;324325NSK_DISPLAY1("Add required capability: %s\n", "can_generate_eraly_class_hook_events");326{327jvmtiCapabilities caps;328329memset(&caps, 0, sizeof(caps));330caps.can_generate_all_class_hook_events = 1;331if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {332return JNI_ERR;333}334}335NSK_DISPLAY0(" ... added\n");336337NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");338{339jvmtiEventCallbacks callbacks;340jint size = (jint)sizeof(callbacks);341342memset(&callbacks, 0, sizeof(callbacks));343callbacks.ClassFileLoadHook = callbackClassFileLoadHook;344if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {345return JNI_ERR;346}347}348NSK_DISPLAY0(" ... set\n");349350/* register agent proc and arg */351if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))352return JNI_ERR;353354return JNI_OK;355}356357/* ============================================================================= */358359}360361362