Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod001/fieldmod001.cpp
40955 views
/*1* Copyright (c) 2003, 2020, 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 <inttypes.h>26#include "jvmti.h"27#include "agent_common.h"28#include "JVMTITools.h"2930extern "C" {313233#define PASSED 034#define STATUS_FAILED 23536typedef struct {37jfieldID fid;38char *m_cls;39char *m_name;40char *m_sig;41jlocation loc;42char *f_cls;43char *f_name;44char *f_sig;45jboolean is_static;46jvalue val;47} writable_watch_info;4849typedef struct {50jfieldID fid;51const char *m_cls;52const char *m_name;53const char *m_sig;54jlocation loc;55const char *f_cls;56const char *f_name;57const char *f_sig;58const jboolean is_static;59jvalue val;60} watch_info;6162static jvmtiEnv *jvmti;63static jvmtiEventCallbacks callbacks;64static jvmtiCapabilities caps;65static jint result = PASSED;66static jboolean printdump = JNI_FALSE;67static int eventsExpected = 0;68static int eventsCount = 0;69static watch_info watches[] = {70{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 1,71"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticBoolean", "Z", JNI_TRUE, {} },72{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 5,73"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticByte", "B", JNI_TRUE, {} },74{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 9,75"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticShort", "S", JNI_TRUE, {} },76{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 13,77"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticInt", "I", JNI_TRUE, {} },78{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 19,79"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticLong", "J", JNI_TRUE, {} },80{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 24,81"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticFloat", "F", JNI_TRUE, {} },82{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 30,83"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticDouble", "D", JNI_TRUE, {} },84{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 35,85"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticChar", "C", JNI_TRUE, {} },86{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 41,87"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticObject", "Ljava/lang/Object;", JNI_TRUE, {} },88{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 47,89"Lnsk/jvmti/FieldModification/fieldmod001a;", "staticArrInt", "[I", JNI_TRUE, {} },9091{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 52,92"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceBoolean", "Z", JNI_FALSE, {} },93{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 58,94"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceByte", "B", JNI_FALSE, {} },95{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 64,96"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceShort", "S", JNI_FALSE, {} },97{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 70,98"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceInt", "I", JNI_FALSE, {} },99{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 77,100"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceLong", "J", JNI_FALSE, {} },101{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 83,102"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceFloat", "F", JNI_FALSE, {} },103{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 90,104"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceDouble", "D", JNI_FALSE, {} },105{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 96,106"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceChar", "C", JNI_FALSE, {} },107{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 103,108"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceObject", "Ljava/lang/Object;", JNI_FALSE, {} },109{ NULL, "Lnsk/jvmti/FieldModification/fieldmod001a;", "run", "()V", 110,110"Lnsk/jvmti/FieldModification/fieldmod001a;", "instanceArrInt", "[I", JNI_FALSE, {} }111};112113void printValue(jvalue val, char *sig) {114switch (*sig) {115case 'J':116printf("0x%x%08x", (jint)(val.j >> 32), (jint)val.j);117break;118case 'F':119printf("%.3f", (double)val.f);120break;121case 'D':122printf("%f", (double)val.d);123break;124case 'L':125case '[':126printf("0x%p", val.l);127break;128case 'Z':129printf("0x%x", val.z);130break;131case 'B':132printf("%d", val.b);133break;134case 'S':135printf("%d", val.s);136break;137case 'C':138printf("0x%x", val.c);139break;140case 'I':141printf("%d", val.i);142break;143default:144printf("0x%x%08x", (jint)(val.j >> 32), (jint)val.j);145break;146}147}148149int isEqual(JNIEnv *env, char *sig, jvalue v1, jvalue v2) {150switch (*sig) {151case 'J':152return (v1.j == v2.j);153case 'F':154return (v1.f == v2.f);155case 'D':156return (v1.d == v2.d);157case 'L':158case '[':159return env->IsSameObject(v1.l, v2.l);160case 'Z':161return (v1.z == v2.z);162case 'B':163return (v1.b == v2.b);164case 'S':165return (v1.s == v2.s);166case 'C':167return (v1.c == v2.c);168case 'I':169return (v1.i == v2.i);170default:171return (1);172}173}174175void JNICALL FieldModification(jvmtiEnv *jvmti_env, JNIEnv *env,176jthread thr, jmethodID method, jlocation location,177jclass field_klass, jobject obj,178jfieldID field, char sig, jvalue new_value) {179jvmtiError err;180jclass cls;181writable_watch_info watch;182char *generic;183size_t i;184185eventsCount++;186if (printdump == JNI_TRUE) {187printf(">>> retrieving modification watch info ...\n");188}189watch.fid = field;190watch.loc = location;191watch.val = new_value;192watch.is_static = (obj == NULL) ? JNI_TRUE : JNI_FALSE;193err = jvmti_env->GetMethodDeclaringClass(method, &cls);194if (err != JVMTI_ERROR_NONE) {195printf("(GetMethodDeclaringClass) unexpected error: %s (%d)\n",196TranslateError(err), err);197result = STATUS_FAILED;198return;199}200err = jvmti_env->GetClassSignature(cls,201&watch.m_cls, &generic);202if (err != JVMTI_ERROR_NONE) {203printf("(GetClassSignature) unexpected error: %s (%d)\n",204TranslateError(err), err);205result = STATUS_FAILED;206return;207}208err = jvmti_env->GetMethodName(method,209&watch.m_name, &watch.m_sig, &generic);210if (err != JVMTI_ERROR_NONE) {211printf("(GetMethodName) unexpected error: %s (%d)\n",212TranslateError(err), err);213result = STATUS_FAILED;214return;215}216err = jvmti_env->GetClassSignature(field_klass,217&watch.f_cls, &generic);218if (err != JVMTI_ERROR_NONE) {219printf("(GetClassSignature) unexpected error: %s (%d)\n",220TranslateError(err), err);221result = STATUS_FAILED;222return;223}224err = jvmti_env->GetFieldName(field_klass, field,225&watch.f_name, &watch.f_sig, &generic);226if (err != JVMTI_ERROR_NONE) {227printf("(GetFieldName) unexpected error: %s (%d)\n",228TranslateError(err), err);229result = STATUS_FAILED;230return;231}232if (printdump == JNI_TRUE) {233printf(">>> class: \"%s\"\n", watch.m_cls);234printf(">>> method: \"%s%s\"\n", watch.m_name, watch.m_sig);235printf(">>> location: 0x%x%08x\n",236(jint)(watch.loc >> 32), (jint)watch.loc);237printf(">>> field cls: \"%s\"\n", watch.f_cls);238printf(">>> field: \"%s:%s\"\n", watch.f_name, watch.f_sig);239printf(">>> object: 0x%p\n", obj);240printf(">>> new value: ");241printValue(watch.val, watch.f_sig);242printf("\n");243}244for (i = 0; i < sizeof(watches)/sizeof(watch_info); i++) {245if (watch.fid == watches[i].fid) {246if (watch.m_cls == NULL ||247strcmp(watch.m_cls, watches[i].m_cls) != 0) {248printf("(watch#%" PRIuPTR ") wrong class: \"%s\", expected: \"%s\"\n",249i, watch.m_cls, watches[i].m_cls);250result = STATUS_FAILED;251}252if (watch.m_name == NULL ||253strcmp(watch.m_name, watches[i].m_name) != 0) {254printf("(watch#%" PRIuPTR ") wrong method name: \"%s\"",255i, watch.m_name);256printf(", expected: \"%s\"\n", watches[i].m_name);257result = STATUS_FAILED;258}259if (watch.m_sig == NULL ||260strcmp(watch.m_sig, watches[i].m_sig) != 0) {261printf("(watch#%" PRIuPTR ") wrong method sig: \"%s\"",262i, watch.m_sig);263printf(", expected: \"%s\"\n", watches[i].m_sig);264result = STATUS_FAILED;265}266if (watch.loc != watches[i].loc) {267printf("(watch#%" PRIuPTR ") wrong location: 0x%x%08x",268i, (jint)(watch.loc >> 32), (jint)watch.loc);269printf(", expected: 0x%x%08x\n",270(jint)(watches[i].loc >> 32), (jint)watches[i].loc);271result = STATUS_FAILED;272}273if (watch.f_name == NULL ||274strcmp(watch.f_name, watches[i].f_name) != 0) {275printf("(watch#%" PRIuPTR ") wrong field name: \"%s\"",276i, watch.f_name);277printf(", expected: \"%s\"\n", watches[i].f_name);278result = STATUS_FAILED;279}280if (watch.f_sig == NULL ||281strcmp(watch.f_sig, watches[i].f_sig) != 0) {282printf("(watch#%" PRIuPTR ") wrong field sig: \"%s\"",283i, watch.f_sig);284printf(", expected: \"%s\"\n", watches[i].f_sig);285result = STATUS_FAILED;286}287if (watch.is_static != watches[i].is_static) {288printf("(watch#%" PRIuPTR ") wrong field type: %s", i,289(watch.is_static == JNI_TRUE) ? "static" : "instance");290printf(", expected: %s\n",291(watches[i].is_static == JNI_TRUE) ? "static" : "instance");292result = STATUS_FAILED;293}294if (!isEqual((JNIEnv *)env, watch.f_sig, watch.val, watches[i].val)) {295printf("(watch#%" PRIuPTR ") wrong new value: ", i);296printValue(watch.val, watch.f_sig);297printf(", expected: ");298printValue(watches[i].val, watch.f_sig);299printf("\n");300result = STATUS_FAILED;301}302return;303}304}305printf("Unexpected field modification catched: 0x%p\n", watch.fid);306result = STATUS_FAILED;307}308309#ifdef STATIC_BUILD310JNIEXPORT jint JNICALL Agent_OnLoad_fieldmod001(JavaVM *jvm, char *options, void *reserved) {311return Agent_Initialize(jvm, options, reserved);312}313JNIEXPORT jint JNICALL Agent_OnAttach_fieldmod001(JavaVM *jvm, char *options, void *reserved) {314return Agent_Initialize(jvm, options, reserved);315}316JNIEXPORT jint JNI_OnLoad_fieldmod001(JavaVM *jvm, char *options, void *reserved) {317return JNI_VERSION_1_8;318}319#endif320jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {321jvmtiError err;322jint res;323324if (options != NULL && strcmp(options, "printdump") == 0) {325printdump = JNI_TRUE;326}327328res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);329if (res != JNI_OK || jvmti == NULL) {330printf("Wrong result of a valid call to GetEnv!\n");331return JNI_ERR;332}333334err = jvmti->GetPotentialCapabilities(&caps);335if (err != JVMTI_ERROR_NONE) {336printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",337TranslateError(err), err);338return JNI_ERR;339}340341err = jvmti->AddCapabilities(&caps);342if (err != JVMTI_ERROR_NONE) {343printf("(AddCapabilities) unexpected error: %s (%d)\n",344TranslateError(err), err);345return JNI_ERR;346}347348err = jvmti->GetCapabilities(&caps);349if (err != JVMTI_ERROR_NONE) {350printf("(GetCapabilities) unexpected error: %s (%d)\n",351TranslateError(err), err);352return JNI_ERR;353}354355if (caps.can_generate_field_modification_events) {356callbacks.FieldModification = &FieldModification;357err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));358if (err != JVMTI_ERROR_NONE) {359printf("(SetEventCallbacks) unexpected error: %s (%d)\n",360TranslateError(err), err);361return JNI_ERR;362}363364err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,365JVMTI_EVENT_FIELD_MODIFICATION, NULL);366if (err != JVMTI_ERROR_NONE) {367printf("Failed to enable JVMTI_EVENT_FIELD_MODIFICATION: %s (%d)\n",368TranslateError(err), err);369return JNI_ERR;370}371} else {372printf("Warning: FieldModification watch is not implemented\n");373}374375return JNI_OK;376}377378JNIEXPORT void JNICALL379Java_nsk_jvmti_FieldModification_fieldmod001_getReady(JNIEnv *env, jclass klass,380jobject obj1, jobject obj2, jobject arr1, jobject arr2) {381jvmtiError err;382jclass cls;383size_t i;384385if (!caps.can_generate_field_modification_events) {386return;387}388389if (printdump == JNI_TRUE) {390printf(">>> setting field modification watches ...\n");391}392cls = env->FindClass("nsk/jvmti/FieldModification/fieldmod001a");393if (cls == NULL) {394printf("Cannot find fieldmod001a class!\n");395result = STATUS_FAILED;396return;397}398for (i = 0; i < sizeof(watches)/sizeof(watch_info); i++) {399if (watches[i].is_static == JNI_TRUE) {400watches[i].fid = env->GetStaticFieldID(401cls, watches[i].f_name, watches[i].f_sig);402} else {403watches[i].fid = env->GetFieldID(404cls, watches[i].f_name, watches[i].f_sig);405}406if (watches[i].fid == NULL) {407printf("Cannot get field ID for \"%s:%s\"\n",408watches[i].f_name, watches[i].f_sig);409result = STATUS_FAILED;410return;411}412err = jvmti->SetFieldModificationWatch(cls, watches[i].fid);413if (err == JVMTI_ERROR_NONE) {414eventsExpected++;415} else {416printf("(SetFieldModificationWatch#%" PRIuPTR ") unexpected error: %s (%d)\n",417i, TranslateError(err), err);418result = STATUS_FAILED;419}420}421422watches[0].val.z = JNI_TRUE;423watches[1].val.b = 1;424watches[2].val.s = 2;425watches[3].val.i = 3;426watches[4].val.j = 4;427watches[5].val.f = 0.5F;428watches[6].val.d = 0.6;429watches[7].val.c = 0x61;430watches[8].val.l = env->NewGlobalRef(obj1);431watches[9].val.l = env->NewGlobalRef(arr1);432433watches[10].val.z = JNI_FALSE;434watches[11].val.b = 10;435watches[12].val.s = 20;436watches[13].val.i = 30;437watches[14].val.j = 40;438watches[15].val.f = 0.05F;439watches[16].val.d = 0.06;440watches[17].val.c = 0x7a;441watches[18].val.l = env->NewGlobalRef(obj2);442watches[19].val.l = env->NewGlobalRef(arr2);443444if (printdump == JNI_TRUE) {445printf(">>> ... done\n");446}447}448449JNIEXPORT jint JNICALL450Java_nsk_jvmti_FieldModification_fieldmod001_check(JNIEnv *env, jclass cls) {451if (eventsCount != eventsExpected) {452printf("Wrong number of field modification events: %d, expected: %d\n",453eventsCount, eventsExpected);454result = STATUS_FAILED;455}456return result;457}458459}460461462