Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c
41159 views
/*1* Copyright (c) 2016, 2017, 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 <stdio.h>24#include <string.h>25#include "jvmti.h"2627#ifdef __cplusplus28extern "C" {29#endif3031#ifndef JNI_ENV_ARG3233#ifdef __cplusplus34#define JNI_ENV_ARG(x, y) y35#define JNI_ENV_PTR(x) x36#else37#define JNI_ENV_ARG(x,y) x, y38#define JNI_ENV_PTR(x) (*x)39#endif4041#endif4243#define TranslateError(err) "JVMTI error"4445#define PASSED 046#define FAILED 24748static const char *EXPECTED_NAME = "java/util/Collections";49static const char *EXC_CNAME = "java/lang/Exception";5051static jvmtiEnv *jvmti = NULL;52static jint result = PASSED;53static jboolean printdump = JNI_FALSE;5455static jboolean with_early_vm_start_capability = JNI_FALSE;56static jboolean with_early_class_hook_capability = JNI_FALSE;5758static jboolean found_class_in_vm_start = JNI_FALSE;59static jboolean found_class_in_primordial = JNI_FALSE;60static jboolean found_class_in_cflh_events = JNI_FALSE;6162static int cflh_events_primordial_count = 0;63static int cflh_events_vm_start_count = 0;6465static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);6667JNIEXPORT68jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {69return Agent_Initialize(jvm, options, reserved);70}7172JNIEXPORT73jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {74return Agent_Initialize(jvm, options, reserved);75}7677JNIEXPORT78jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {79return JNI_VERSION_9;80}8182static83jint throw_exc(JNIEnv *env, char *msg) {84jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));8586if (exc_class == NULL) {87printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);88return -1;89}90return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);91}9293static void JNICALL94Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,95jclass class_being_redefined,96jobject loader, const char* name, jobject protection_domain,97jint class_data_len, const unsigned char* class_data,98jint *new_class_data_len, unsigned char** new_class_data) {99jvmtiPhase phase;100jvmtiError err;101102err = (*jvmti)->GetPhase(jvmti_env, &phase);103if (err != JVMTI_ERROR_NONE) {104printf("ClassFileLoadHook event: GetPhase error: %s (%d)\n", TranslateError(err), err);105result = FAILED;106return;107}108109if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {110if (phase == JVMTI_PHASE_START) {111cflh_events_vm_start_count++;112if(strcmp(name, EXPECTED_NAME) == 0) {113found_class_in_vm_start = JNI_TRUE;114}115} else {116cflh_events_primordial_count++;117if(strcmp(name, EXPECTED_NAME) == 0) {118found_class_in_primordial = JNI_TRUE;119}120}121}122123if(strcmp(name, EXPECTED_NAME) == 0) {124found_class_in_cflh_events = JNI_TRUE;125}126127if (printdump == JNI_TRUE) {128printf(">>> ClassFileLoadHook event: phase(%d), class name %s\n", phase, name);129}130}131132static133jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {134jint res, size;135jvmtiCapabilities caps;136jvmtiEventCallbacks callbacks;137jvmtiError err;138139printf("agent options: %s\n", options);140if (options != NULL) {141if (strstr(options, "with_early_vmstart") != NULL) {142with_early_vm_start_capability = JNI_TRUE;143}144if (strstr(options, "with_early_class_hook") != NULL) {145with_early_class_hook_capability = JNI_TRUE;146}147if (strstr(options, "printdump") != NULL) {148printdump = JNI_TRUE;149}150}151152res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),153JVMTI_VERSION_9);154if (res != JNI_OK || jvmti == NULL) {155printf(" Error: wrong result of a valid call to GetEnv!\n");156return JNI_ERR;157}158159printf("Enabling following capabilities: can_generate_all_class_hook_events");160memset(&caps, 0, sizeof(caps));161caps.can_generate_all_class_hook_events = 1;162if (with_early_vm_start_capability == JNI_TRUE) {163printf(", can_generate_early_vmstart");164caps.can_generate_early_vmstart = 1;165}166if (with_early_class_hook_capability == JNI_TRUE) {167printf(", can_generate_early_class_hook_events");168caps.can_generate_early_class_hook_events = 1;169}170printf("\n");171172err = (*jvmti)->AddCapabilities(jvmti, &caps);173if (err != JVMTI_ERROR_NONE) {174printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);175return JNI_ERR;176}177178size = (jint)sizeof(callbacks);179180memset(&callbacks, 0, sizeof(callbacks));181callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;182183err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);184if (err != JVMTI_ERROR_NONE) {185printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);186return JNI_ERR;187}188189err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);190if (err != JVMTI_ERROR_NONE) {191printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);192return JNI_ERR;193}194195return JNI_OK;196}197198JNIEXPORT jint JNICALL199Java_MAAClassFileLoadHook_check(JNIEnv *env, jclass cls) {200jobject loader = NULL;201202if (jvmti == NULL) {203throw_exc(env, "JVMTI client was not properly loaded!\n");204return FAILED;205}206207/*208* Expecting ClassFileLoadHook events in the VM Start phase if early_vm_start is enabled.209*/210if (with_early_vm_start_capability == JNI_TRUE && cflh_events_vm_start_count == 0) {211throw_exc(env, "Didn't get ClassFileLoadHook events in start phase!\n");212return FAILED;213}214215if (with_early_class_hook_capability == JNI_TRUE) {216/*217* Expecting that we get ClassFileLoadHook events in the Primordial phase218* when can_generate_all_class_hook_events and can_generate_early_class_hook_events219* capabilities are enabled.220*/221if (cflh_events_primordial_count == 0) {222throw_exc(env, "Didn't get ClassFileLoadHook events in primordial phase!\n");223return FAILED;224}225} else {226/*227* Expecting that we don't get ClassFileLoadHook events in the Primordial phase228* when can_generate_early_class_hook_events capability is disabled.229*/230if (cflh_events_primordial_count != 0) {231throw_exc(env, "Get ClassFileLoadHook events in primordial phase!\n");232return FAILED;233}234}235236237if (with_early_vm_start_capability == JNI_TRUE) {238/*239* Expecting that "java/util/Collections" class from java.base module is present in the240* ClassFileLoadHook events during VM Start phase when can_generate_early_vmstart241* capability is enabled.242*/243printf("Expecting to find '%s' class in ClassFileLoadHook events during VM early start phase.\n", EXPECTED_NAME);244if (found_class_in_vm_start == JNI_FALSE) {245throw_exc(env, "Unable to find expected class in ClassLoad events during VM early start phase!\n");246return FAILED;247}248} else if (with_early_class_hook_capability == JNI_TRUE) {249/*250* Expecting that "java/util/Collections" class from java.base module is present in the251* ClassFileLoadHook events during Primordial phase when can_generate_all_class_hook_events252* and can_generate_early_class_hook_events capabilities are enabled and can_generate_early_vmstart253* capability is disabled.254*/255printf("Expecting to find '%s' class in ClassFileLoadHook events during VM primordial phase.\n", EXPECTED_NAME);256if (found_class_in_primordial == JNI_FALSE) {257throw_exc(env, "Unable to find expected class in ClassFileLoadHook events during primordial phase!\n");258return FAILED;259}260} else {261/*262* Expecting that "java/util/Collections" class from java.base module is not present in the263* ClassFileLoadHook events when can_generate_all_class_hook_events, can_generate_early_class_hook_events264* and can_generate_early_vmstart capabilities are disabled.265*/266printf("Expecting that '%s' class is absent in ClassLoadHook events.\n", EXPECTED_NAME);267if (found_class_in_cflh_events == JNI_TRUE) {268throw_exc(env, "Class is found in ClassFileLoadHook events!\n");269return FAILED;270}271}272273return result;274}275276#ifdef __cplusplus277}278#endif279280281