Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions/libAllowedFunctions.c
41155 views
/*1* Copyright (c) 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 <stdint.h>24#include <stdio.h>25#include <stdlib.h>26#include <string.h>27#include "jvmti.h"2829#ifdef __cplusplus30extern "C" {31#endif3233#ifndef JNI_ENV_ARG3435#ifdef __cplusplus36#define JNI_ENV_ARG(x, y) y37#define JNI_ENV_PTR(x) x38#else39#define JNI_ENV_ARG(x,y) x, y40#define JNI_ENV_PTR(x) (*x)41#endif4243#endif4445#define PASSED 046#define FAILED 24748static jint result = PASSED;4950static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);5152JNIEXPORT53jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {54return Agent_Initialize(jvm, options, reserved);55}5657JNIEXPORT58jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {59return Agent_Initialize(jvm, options, reserved);60}6162JNIEXPORT63jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {64return JNI_VERSION_9;65}6667static void check_jvmti_error(jvmtiEnv *jvmti, char* fname, jvmtiError err) {68if (err != JVMTI_ERROR_NONE) {69printf(" ## %s error: %d\n", fname, err);70exit(err);71}72}7374static void deallocate(jvmtiEnv *jvmti, char* mem) {75jvmtiError err = (*jvmti)->Deallocate(jvmti, (unsigned char*)mem);76check_jvmti_error(jvmti, "Deallocate", err);77}7879static void get_phase(jvmtiEnv *jvmti, jvmtiPhase *phase_ptr) {80jvmtiError err = (*jvmti)->GetPhase(jvmti, phase_ptr);81check_jvmti_error(jvmti, "GetPhase", err);82}8384static jthread get_cur_thread(jvmtiEnv *jvmti) {85jthread cur_thread = NULL;86jvmtiError err = (*jvmti)->GetCurrentThread(jvmti, &cur_thread);87check_jvmti_error(jvmti, "GetCurrentThread", err);88return cur_thread;89}9091static intptr_t get_thread_local(jvmtiEnv *jvmti, jthread thread) {92void *val = NULL;93jvmtiError err = (*jvmti)->GetThreadLocalStorage(jvmti, thread, &val);94check_jvmti_error(jvmti, "GetThreadLocalStorage", err);95return (intptr_t)val;96}9798static void set_thread_local(jvmtiEnv *jvmti, jthread thread, intptr_t x) {99void *val = (void*)x;100jvmtiError err = (*jvmti)->SetThreadLocalStorage(jvmti, thread, val);101check_jvmti_error(jvmti, "SetThreadLocalStorage", err);102}103104static void print_class_status(jvmtiEnv *jvmti, jclass klass) {105jint status = 0;106jvmtiError err = (*jvmti)->GetClassStatus(jvmti, klass, &status);107108check_jvmti_error(jvmti, "GetClassStatus", err);109// This function is only used in a ClassPrepare event context110if ((status & JVMTI_CLASS_STATUS_VERIFIED) == 0 ||111(status & JVMTI_CLASS_STATUS_PREPARED) == 0 ||112(status & JVMTI_CLASS_STATUS_INITIALIZED) != 0 ||113(status & JVMTI_CLASS_STATUS_ERROR) != 0) {114printf(" ## Error: unexpected class status: 0x%08x\n", status);115}116printf(" Class status: 0x%08x\n", status);117}118119static void print_class_signature(jvmtiEnv *jvmti, jclass klass) {120char* name = NULL;121jvmtiError err = (*jvmti)->GetClassSignature(jvmti, klass, &name, NULL);122123check_jvmti_error(jvmti, "GetClassSignature", err);124if (name != NULL) {125printf(" class: '%s'\n", name);126deallocate(jvmti, name);127}128}129130static void print_class_source_file_name(jvmtiEnv *jvmti, jclass klass) {131char* name = NULL;132jvmtiError err = (*jvmti)->GetSourceFileName(jvmti, klass, &name);133134check_jvmti_error(jvmti, "GetSourceFileName", err);135if (name != NULL) {136printf(" Class source file name: '%s'\n", name);137deallocate(jvmti, name);138}139}140141static void print_class_info(jvmtiEnv *jvmti, jclass klass) {142jint mods = 0;143jboolean is_interface = JNI_FALSE;144jboolean is_array = JNI_FALSE;145jboolean is_modifiable = JNI_FALSE;146jvmtiError err = (*jvmti)->GetClassModifiers(jvmti, klass, &mods);147148check_jvmti_error(jvmti, "GetClassModifiers", err);149printf(" Class modifiers: 0x%08x\n", mods);150151err = (*jvmti)->IsInterface(jvmti, klass, &is_interface);152check_jvmti_error(jvmti, "IsInterface", err);153printf(" Class is interface: %d\n", is_interface);154155err = (*jvmti)->IsArrayClass(jvmti, klass, &is_array);156check_jvmti_error(jvmti, "IsArrayClass", err);157printf(" Class is array: %d\n", is_array);158159err = (*jvmti)->IsModifiableClass(jvmti, klass, &is_modifiable);160check_jvmti_error(jvmti, "IsModifiableClass", err);161printf(" Class is modifiable: %d\n", is_modifiable);162}163164static jint get_class_methods(jvmtiEnv *jvmti, jclass klass, jmethodID** methods_ptr) {165jint count = 0;166jvmtiError err = (*jvmti)->GetClassMethods(jvmti, klass, &count, methods_ptr);167check_jvmti_error(jvmti, "GetClassMethods", err);168return count;169}170171static jint get_class_fields(jvmtiEnv *jvmti, jclass klass, jfieldID** fields_ptr) {172jint count = 0;173jvmtiError err = (*jvmti)->GetClassFields(jvmti, klass, &count, fields_ptr);174check_jvmti_error(jvmti, "GetClassFields", err);175return count;176}177178static void print_method_name_sign(jvmtiEnv *jvmti, jmethodID method) {179char* name = NULL;180char* sign = NULL;181jvmtiError err = (*jvmti)->GetMethodName(jvmti, method, &name, &sign, NULL);182183check_jvmti_error(jvmti, "GetMethodName", err);184printf(" Method: %s%s\n", name, sign);185deallocate(jvmti, name);186deallocate(jvmti, sign);187}188189static void print_method_declaring_class(jvmtiEnv *jvmti, jmethodID method) {190jclass dclass = NULL;191jvmtiError err = (*jvmti)->GetMethodDeclaringClass(jvmti, method, &dclass);192193check_jvmti_error(jvmti, "GetMethodDeclaringClass", err);194printf(" Method declaring");195print_class_signature(jvmti, dclass);196}197198static void print_method_info(jvmtiEnv *jvmti, jmethodID method) {199jint mods = 0;200jint locals_max = 0;201jint args_size = 0;202jboolean is_native = JNI_FALSE;203jboolean is_synth = JNI_FALSE;204jboolean is_obsolete = JNI_FALSE;205jvmtiError err = (*jvmti)->GetMethodModifiers(jvmti, method, &mods);206207check_jvmti_error(jvmti, "GetMethodModifiers", err);208printf(" Method modifiers: 0x%08x\n", mods);209210err = (*jvmti)->IsMethodNative(jvmti, method, &is_native);211check_jvmti_error(jvmti, "IsMethodNative", err);212printf(" Method is native: %d\n", is_native);213214if (is_native == JNI_FALSE) {215err = (*jvmti)->GetMaxLocals(jvmti, method, &locals_max);216check_jvmti_error(jvmti, "GetMaxLocals", err);217printf(" Method max locals: %d\n", locals_max);218219err = (*jvmti)->GetArgumentsSize(jvmti, method, &args_size);220check_jvmti_error(jvmti, "GetArgumentsSize", err);221printf(" Method arguments size: %d\n", args_size);222}223224err = (*jvmti)->IsMethodSynthetic(jvmti, method, &is_synth);225check_jvmti_error(jvmti, "IsMethodSynthetic", err);226printf(" Method is synthetic: %d\n", is_synth);227228err = (*jvmti)->IsMethodObsolete(jvmti, method, &is_obsolete);229check_jvmti_error(jvmti, "IsMethodObsolete", err);230printf(" Method is obsolete: %d\n", is_obsolete);231}232233static void test_method_functions(jvmtiEnv *jvmti, jmethodID method) {234print_method_name_sign(jvmti, method);235print_method_declaring_class(jvmti, method);236print_method_info(jvmti, method);237}238239static void print_field_name_sign(jvmtiEnv *jvmti, jclass klass, jfieldID field) {240char* name = NULL;241char* sign = NULL;242jvmtiError err = (*jvmti)->GetFieldName(jvmti, klass, field, &name, &sign, NULL);243244check_jvmti_error(jvmti, "GetFieldName", err);245printf(" Field: %s %s\n", sign, name);246deallocate(jvmti, name);247deallocate(jvmti, sign);248}249250static void print_field_declaring_class(jvmtiEnv *jvmti, jclass klass, jfieldID field) {251jclass dclass = NULL;252jvmtiError err = (*jvmti)->GetFieldDeclaringClass(jvmti, klass, field, &dclass);253254check_jvmti_error(jvmti, "GetFieldDeclaringClass", err);255printf(" Field declaring");256print_class_signature(jvmti, dclass);257}258259static void print_field_info(jvmtiEnv *jvmti, jclass klass, jfieldID field) {260jint mods = 0;261jboolean is_synth = JNI_FALSE;262jvmtiError err = (*jvmti)->GetFieldModifiers(jvmti, klass, field, &mods);263264check_jvmti_error(jvmti, "GetFieldModifiers", err);265printf(" Field modifiers: 0x%08x\n", mods);266267err = (*jvmti)->IsFieldSynthetic(jvmti, klass, field, &is_synth);268check_jvmti_error(jvmti, "IsFieldSynthetic", err);269printf(" Field is synthetic: %d\n", is_synth);270}271272static void test_field_functions(jvmtiEnv *jvmti, jclass klass, jfieldID field) {273print_field_name_sign(jvmti, klass, field);274print_field_declaring_class(jvmti, klass, field);275print_field_info(jvmti, klass, field);276}277278static void test_class_functions(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) {279jint count = 0;280jint idx = 0;281jmethodID* methods = NULL;282jfieldID* fields = NULL;283284print_class_signature(jvmti, klass);285print_class_status(jvmti, klass);286print_class_source_file_name(jvmti, klass);287print_class_info(jvmti, klass);288289count = get_class_methods(jvmti, klass, &methods);290for (idx = 0; idx < count; idx++) {291test_method_functions(jvmti, methods[idx]);292}293if (methods != NULL) {294deallocate(jvmti, (char*)methods);295}296count = get_class_fields(jvmti, klass, &fields);297for (idx = 0; idx < count; idx++) {298test_field_functions(jvmti, klass, fields[idx]);299}300if (fields != NULL) {301deallocate(jvmti, (char*)fields);302}303}304305static void JNICALL306VMStart(jvmtiEnv *jvmti, JNIEnv* jni) {307jvmtiPhase phase;308309printf("VMStart event\n");310get_phase(jvmti, &phase);311if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE) {312printf(" ## Error: unexpected phase: %d, expected: %d or %d\n",313phase, JVMTI_PHASE_START, JVMTI_PHASE_LIVE);314result = FAILED;315}316}317318static void JNICALL319VMInit(jvmtiEnv *jvmti, JNIEnv* jnii, jthread thread) {320jvmtiPhase phase;321322printf("VMInit event\n");323get_phase(jvmti, &phase);324if (phase != JVMTI_PHASE_LIVE) {325printf(" ## Error: unexpected phase: %d, expected: %d\n",326phase, JVMTI_PHASE_LIVE);327result = FAILED;328}329}330331static void JNICALL332ClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) {333static const jint EVENTS_LIMIT = 2;334static jint event_no = 0;335jthread cur_thread = get_cur_thread(jvmti);336jvmtiPhase phase;337intptr_t exp_val = 777;338intptr_t act_val;339340get_phase(jvmti, &phase);341if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE) {342printf(" ## Error: unexpected phase: %d, expected: %d or %d\n",343phase, JVMTI_PHASE_START, JVMTI_PHASE_LIVE);344return;345}346if (phase == JVMTI_PHASE_START && event_no < EVENTS_LIMIT) {347printf("\nClassPrepare event during the start phase: #%d\n", event_no);348// Test the JVMTI class functions during the start phase349test_class_functions(jvmti, env, thread, klass);350351set_thread_local(jvmti, thread, exp_val);352act_val = get_thread_local(jvmti, cur_thread);353if (act_val != exp_val) { // Actual value does not match the expected354printf(" ## Unexpected thread-local: %ld, expected: %ld\n",355(long)act_val, (long)exp_val);356result = FAILED;357} else {358printf(" Got expected thread-local: %ld\n", (long)exp_val);359}360event_no++;361}362}363364static365jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {366jboolean with_early_vm_start_capability = JNI_FALSE;367jvmtiEnv *jvmti = NULL;368jvmtiError err;369jint res, size;370jvmtiCapabilities caps;371jvmtiEventCallbacks callbacks;372373if (options != NULL && strstr(options, "with_early_vmstart") != NULL) {374with_early_vm_start_capability = JNI_TRUE;375}376377res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), JVMTI_VERSION_9);378if (res != JNI_OK || jvmti == NULL) {379printf("## Agent_Initialize: Error in GetEnv: res: %d, jvmti env: %p\n", res, jvmti);380return JNI_ERR;381}382383memset(&caps, 0, sizeof(caps));384caps.can_get_source_file_name = 1;385caps.can_get_synthetic_attribute = 1;386387if (with_early_vm_start_capability == JNI_TRUE) {388caps.can_generate_early_vmstart = 1;389printf("Capability enabled: can_generate_early_vmstart\n");390} else {391printf("Capability disabled: can_generate_early_vmstart\n");392}393err = (*jvmti)->AddCapabilities(jvmti, &caps);394check_jvmti_error(jvmti, "## Agent_Initialize: AddCapabilites", err);395396size = (jint)sizeof(callbacks);397memset(&callbacks, 0, size);398callbacks.VMStart = VMStart;399callbacks.VMInit = VMInit;400callbacks.ClassPrepare = ClassPrepare;401402err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);403check_jvmti_error(jvmti, "## Agent_Initialize: SetEventCallbacks", err);404405err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL);406check_jvmti_error(jvmti, "## Agent_Initialize: SetEventNotificationMode VM_START", err);407408err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);409check_jvmti_error(jvmti, "## Agent_Initialize: SetEventNotificationMode VM_INIT", err);410411err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);412check_jvmti_error(jvmti, "## Agent_Initialize: SetEventNotificationMode CLASS_PREPARE", err);413return JNI_OK;414}415416JNIEXPORT jint JNICALL417Java_AllowedFunctions_check(JNIEnv *env, jclass cls) {418return result;419}420421#ifdef __cplusplus422}423#endif424425426