Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk003/classfloadhk003.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/classfloadhk003"38#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk003r"39#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"40#define TESTED_CLASSLOADER_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk003ClassLoader"41#define TESTED_CLASSLOADER_SIG "L" TESTED_CLASSLOADER_NAME ";"4243#define CLASSLOADER_FIELD_NAME "classLoader"44#define BYTECODE_FIELD_SIG "[B"45#define ORIG_BYTECODE_FIELD_NAME "origClassBytes"4647static jobject classLoader = NULL;48static jint origClassSize = 0;49static unsigned char* origClassBytes = NULL;5051static volatile int eventsCount = 0;5253/* ============================================================================= */5455/** Check (strictly or not) if bytecode has expected size and bytes or complain an error. */56static int checkBytecode(const char kind[], jint size, const unsigned char bytes[],57jint expectedSize, const unsigned char expectedBytes[],58int strict) {59int success = NSK_TRUE;6061NSK_DISPLAY3("Check %s bytecode: 0x%p:%d\n", kind, (void*)bytes, (int)size);62if (nsk_getVerboseMode()) {63nsk_printHexBytes(" ", 16, size, bytes);64}6566if (bytes == NULL) {67NSK_COMPLAIN2("Unexpected NULL pointer to %s bytecode in CLASS_FILE_LOAD_HOOK: 0x%p\n",68kind, (void*)bytes);69return NSK_FALSE;70}7172if (size <= 0) {73NSK_COMPLAIN2("Unexpected zero size of %s bytecode in CLASS_FILE_LOAD_HOOK: %d\n",74kind, (int)size);75return NSK_FALSE;76}7778if (strict) {79if (size != expectedSize) {80NSK_COMPLAIN3("Unexpected size of %s bytecode in CLASS_FILE_LOAD_HOOK:\n"81"# got size: %d\n"82"# expected: %d\n",83kind, (int)size, (int)expectedSize);84success = NSK_FALSE;85} else {86jint different = 0;87jint i;8889for (i = 0; i < size; i++) {90if (bytes[i] != expectedBytes[i]) {91different++;92}93}94if (different > 0) {95NSK_COMPLAIN2("Unexpected bytes in %s bytecode in CLASS_FILE_LOAD_HOOK:\n"96"# different bytes: %d\n"97"# total bytes: %d\n",98(int)different, (int)size);99success = NSK_FALSE;100}101}102103if (!success) {104NSK_COMPLAIN2("Got %s bytecode is not equal to expected bytecode: %d bytes\n",105kind, expectedSize);106if (nsk_getVerboseMode()) {107nsk_printHexBytes(" ", 16, expectedSize, expectedBytes);108}109} else {110NSK_DISPLAY1("All %s bytecode is equal to expected one\n", kind);111}112}113114return success;115}116117/** Get classfile bytecode from a static field of given class. */118static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,119const char fieldName[], const char fieldSig[],120jint* size, unsigned char* *bytes) {121122jfieldID fieldID = NULL;123jbyteArray array = NULL;124jbyte* elements;125int i;126127NSK_DISPLAY1("Find static field: %s\n", fieldName);128if (!NSK_JNI_VERIFY(jni, (fieldID =129jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {130nsk_jvmti_setFailStatus();131return NSK_FALSE;132}133NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);134135NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);136if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)137jni->GetStaticObjectField(cls, fieldID)) != NULL)) {138nsk_jvmti_setFailStatus();139return NSK_FALSE;140}141NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);142143if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {144nsk_jvmti_setFailStatus();145return NSK_FALSE;146}147NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);148149{150jboolean isCopy;151if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {152nsk_jvmti_setFailStatus();153return NSK_FALSE;154}155}156NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);157158if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {159nsk_jvmti_setFailStatus();160return NSK_FALSE;161}162NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);163164for (i = 0; i < *size; i++) {165(*bytes)[i] = (unsigned char)elements[i];166}167NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);168169NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);170NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));171NSK_DISPLAY0(" ... released\n");172173return NSK_TRUE;174}175176/** Get global reference to object from a static field of given class. */177static jobject getObject(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,178const char fieldName[], const char fieldSig[]) {179180jfieldID fieldID = NULL;181jobject obj = NULL;182183NSK_DISPLAY1("Find static field: %s\n", fieldName);184if (!NSK_JNI_VERIFY(jni, (fieldID =185jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {186nsk_jvmti_setFailStatus();187return NULL;188}189NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);190191NSK_DISPLAY1("Get object from static field: %s\n", fieldName);192if (!NSK_JNI_VERIFY(jni, (obj = jni->GetStaticObjectField(cls, fieldID)) != NULL)) {193nsk_jvmti_setFailStatus();194return NULL;195}196NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)obj);197198NSK_DISPLAY1("Make global reference to object: 0x%p\n", obj);199if (!NSK_JNI_VERIFY(jni, (obj = jni->NewGlobalRef(obj)) != NULL)) {200nsk_jvmti_setFailStatus();201return NULL;202}203NSK_DISPLAY1(" ... got global ref: 0x%p\n", (void*)obj);204205return obj;206}207208/* ============================================================================= */209210/** Agent algorithm. */211static void JNICALL212agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {213NSK_DISPLAY0("Wait for debuggee to become ready\n");214if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))215return;216217/* perform testing */218{219{220jclass debugeeClass = NULL;221222NSK_DISPLAY0(">>> Obtain debuggee class\n");223NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);224if (!NSK_JNI_VERIFY(jni, (debugeeClass =225jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {226nsk_jvmti_setFailStatus();227return;228}229NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);230231NSK_DISPLAY0(">>> Obtain classloader of tested class\n");232if (!NSK_VERIFY((classLoader =233getObject(jvmti, jni, debugeeClass, CLASSLOADER_FIELD_NAME,234TESTED_CLASSLOADER_SIG)) != NULL))235return;236237NSK_DISPLAY0(">>> Obtain original bytecode of tested class\n");238if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,239ORIG_BYTECODE_FIELD_NAME,240BYTECODE_FIELD_SIG,241&origClassSize, &origClassBytes)))242return;243}244245NSK_DISPLAY0(">>> Testcase #1: Load tested class and check CLASS_FILE_LOAD_HOOK event\n");246{247jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;248249NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");250if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))251return;252NSK_DISPLAY0(" ... event enabled\n");253254NSK_DISPLAY0("Let debugee to load tested class\n");255if (!NSK_VERIFY(nsk_jvmti_resumeSync()))256return;257NSK_DISPLAY0("Wait for tested class to be loaded\n");258if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))259return;260261NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");262if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {263NSK_DISPLAY0(" ... event disabled\n");264}265266NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");267if (eventsCount != 1) {268NSK_COMPLAIN3("Unexpected number of %s events for tested class:\n"269"# got events: %d\n"270"# expected: %d\n",271"CLASS_FILE_LOAD_HOOK",272eventsCount, 1);273nsk_jvmti_setFailStatus();274} else {275NSK_DISPLAY1(" ... received: %d events\n", eventsCount);276}277}278279NSK_DISPLAY0(">>> Clean used data\n");280{281NSK_DISPLAY1("Delete global reference to classloader object: 0x%p\n", (void*)classLoader);282jni->DeleteGlobalRef(classLoader);283284NSK_DISPLAY1("Deallocate classfile bytes array: 0x%p\n", (void*)origClassBytes);285if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(origClassBytes))) {286nsk_jvmti_setFailStatus();287}288}289}290291NSK_DISPLAY0("Let debugee to finish\n");292if (!NSK_VERIFY(nsk_jvmti_resumeSync()))293return;294}295296/* ============================================================================= */297298/** Callback for CLASS_FILE_LOAD_HOOK event **/299static void JNICALL300callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,301jclass class_being_redefined,302jobject loader, const char* name, jobject protection_domain,303jint class_data_len, const unsigned char* class_data,304jint *new_class_data_len, unsigned char** new_class_data) {305306NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",307nsk_null_string(name), (void*)loader, (void*)class_being_redefined,308(void*)class_data, (int)class_data_len);309310if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {311NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);312eventsCount++;313314NSK_DISPLAY1("Check class_being_redefined: 0x%p\n", (void*)class_being_redefined);315if (class_being_redefined != NULL) {316NSK_COMPLAIN1("Unexpected not NULL class_being_redefined in CLASS_FILE_LOAD_HOOK: 0x%p\n",317(void*)class_being_redefined);318nsk_jvmti_setFailStatus();319}320321NSK_DISPLAY1("Check classloader: 0x%p\n", (void*)loader);322if (loader == NULL) {323NSK_COMPLAIN1("Unexpected NULL classloader in CLASS_FILE_LOAD_HOOK: 0x%p\n",324(void*)loader);325nsk_jvmti_setFailStatus();326} else if (!jni->IsSameObject(loader, classLoader)) {327NSK_COMPLAIN2("Unexpected classloader in CLASS_FILE_LOAD_HOOK for tested class:\n"328"# got classloder: 0x%p\n"329"# expected same as: 0x%p\n",330(void*)loader, (void*)classLoader);331nsk_jvmti_setFailStatus();332}333334if (!checkBytecode("original", class_data_len, class_data,335origClassSize, origClassBytes, NSK_TRUE)) {336nsk_jvmti_setFailStatus();337}338}339}340341/* ============================================================================= */342343/** Agent library initialization. */344#ifdef STATIC_BUILD345JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk003(JavaVM *jvm, char *options, void *reserved) {346return Agent_Initialize(jvm, options, reserved);347}348JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk003(JavaVM *jvm, char *options, void *reserved) {349return Agent_Initialize(jvm, options, reserved);350}351JNIEXPORT jint JNI_OnLoad_classfloadhk003(JavaVM *jvm, char *options, void *reserved) {352return JNI_VERSION_1_8;353}354#endif355jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {356jvmtiEnv* jvmti = NULL;357358/* init framework and parse options */359if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))360return JNI_ERR;361362timeout = nsk_jvmti_getWaitTime() * 60 * 1000;363364/* create JVMTI environment */365if (!NSK_VERIFY((jvmti =366nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))367return JNI_ERR;368369NSK_DISPLAY1("Add required capability: %s\n", "can_generate_eraly_class_hook_events");370{371jvmtiCapabilities caps;372373memset(&caps, 0, sizeof(caps));374caps.can_generate_all_class_hook_events = 1;375if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {376return JNI_ERR;377}378}379NSK_DISPLAY0(" ... added\n");380381NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");382{383jvmtiEventCallbacks callbacks;384jint size = (jint)sizeof(callbacks);385386memset(&callbacks, 0, sizeof(callbacks));387callbacks.ClassFileLoadHook = callbackClassFileLoadHook;388if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {389return JNI_ERR;390}391}392NSK_DISPLAY0(" ... set\n");393394/* register agent proc and arg */395if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))396return JNI_ERR;397398return JNI_OK;399}400401/* ============================================================================= */402403}404405406