Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod002/fieldmod002.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;58jboolean 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/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,71"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticBoolean", "Z", JNI_TRUE, {} },72{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,73"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticByte", "B", JNI_TRUE, {} },74{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,75"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticShort", "S", JNI_TRUE, {} },76{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,77"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticInt", "I", JNI_TRUE, {} },78{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,79"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticLong", "J", JNI_TRUE, {} },80{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,81"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticFloat", "F", JNI_TRUE, {} },82{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,83"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticDouble", "D", JNI_TRUE, {} },84{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,85"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticChar", "C", JNI_TRUE, {} },86{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,87"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticObject", "Ljava/lang/Object;", JNI_TRUE, {} },88{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,89"Lnsk/jvmti/FieldModification/fieldmod002a;", "staticArrInt", "[I", JNI_TRUE, {} },9091{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,92"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceBoolean", "Z", JNI_FALSE, {} },93{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,94"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceByte", "B", JNI_FALSE, {} },95{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,96"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceShort", "S", JNI_FALSE, {} },97{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,98"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceInt", "I", JNI_FALSE, {} },99{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,100"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceLong", "J", JNI_FALSE, {} },101{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,102"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceFloat", "F", JNI_FALSE, {} },103{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,104"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceDouble", "D", JNI_FALSE, {} },105{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,106"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceChar", "C", JNI_FALSE, {} },107{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,108"Lnsk/jvmti/FieldModification/fieldmod002a;", "instanceObject", "Ljava/lang/Object;", JNI_FALSE, {} },109{ NULL, "Lnsk/jvmti/FieldModification/fieldmod002;", "check", "(Ljava/lang/Object;)I", 0,110"Lnsk/jvmti/FieldModification/fieldmod002a;", "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.is_static = (obj == NULL) ? JNI_TRUE : JNI_FALSE;192watch.val = new_value;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, &watch.m_name, &watch.m_sig, &generic);209if (err != JVMTI_ERROR_NONE) {210printf("(GetMethodName) unexpected error: %s (%d)\n",211TranslateError(err), err);212result = STATUS_FAILED;213return;214}215err = jvmti_env->GetClassSignature(field_klass,216&watch.f_cls, &generic);217if (err != JVMTI_ERROR_NONE) {218printf("(GetClassSignature) unexpected error: %s (%d)\n",219TranslateError(err), err);220result = STATUS_FAILED;221return;222}223err = jvmti_env->GetFieldName(field_klass, field,224&watch.f_name, &watch.f_sig, &generic);225if (err != JVMTI_ERROR_NONE) {226printf("(GetFieldName) unexpected error: %s (%d)\n",227TranslateError(err), err);228result = STATUS_FAILED;229return;230}231if (printdump == JNI_TRUE) {232printf(">>> class: \"%s\"\n", watch.m_cls);233printf(">>> method: \"%s%s\"\n", watch.m_name, watch.m_sig);234printf(">>> location: 0x%x%08x\n",235(jint)(watch.loc >> 32), (jint)watch.loc);236printf(">>> field cls: \"%s\"\n", watch.f_cls);237printf(">>> field: \"%s:%s\"\n", watch.f_name, watch.f_sig);238printf(">>> object: 0x%p\n", obj);239printf(">>> new value: ");240printValue(watch.val, watch.f_sig);241printf("\n");242}243for (i = 0; i < sizeof(watches)/sizeof(watch_info); i++) {244if (watch.fid == watches[i].fid) {245if (watch.m_cls == NULL ||246strcmp(watch.m_cls, watches[i].m_cls) != 0) {247printf("(watch#%" PRIuPTR ") wrong class: \"%s\", expected: \"%s\"\n",248i, watch.m_cls, watches[i].m_cls);249result = STATUS_FAILED;250}251if (watch.m_name == NULL ||252strcmp(watch.m_name, watches[i].m_name) != 0) {253printf("(watch#%" PRIuPTR ") wrong method name: \"%s\"",254i, watch.m_name);255printf(", expected: \"%s\"\n", watches[i].m_name);256result = STATUS_FAILED;257}258if (watch.m_sig == NULL ||259strcmp(watch.m_sig, watches[i].m_sig) != 0) {260printf("(watch#%" PRIuPTR ") wrong method sig: \"%s\"",261i, watch.m_sig);262printf(", expected: \"%s\"\n", watches[i].m_sig);263result = STATUS_FAILED;264}265if (watch.loc != watches[i].loc) {266printf("(watch#%" PRIuPTR ") wrong location: 0x%x%08x",267i, (jint)(watch.loc >> 32), (jint)watch.loc);268printf(", expected: 0x%x%08x\n",269(jint)(watches[i].loc >> 32), (jint)watches[i].loc);270result = STATUS_FAILED;271}272if (watch.f_name == NULL ||273strcmp(watch.f_name, watches[i].f_name) != 0) {274printf("(watch#%" PRIuPTR ") wrong field name: \"%s\"",275i, watch.f_name);276printf(", expected: \"%s\"\n", watches[i].f_name);277result = STATUS_FAILED;278}279if (watch.f_sig == NULL ||280strcmp(watch.f_sig, watches[i].f_sig) != 0) {281printf("(watch#%" PRIuPTR ") wrong field sig: \"%s\"",282i, watch.f_sig);283printf(", expected: \"%s\"\n", watches[i].f_sig);284result = STATUS_FAILED;285}286if (watch.is_static != watches[i].is_static) {287printf("(watch#%" PRIuPTR ") wrong field type: %s", i,288(watch.is_static == JNI_TRUE) ? "static" : "instance");289printf(", expected: %s\n",290(watches[i].is_static == JNI_TRUE) ? "static" : "instance");291result = STATUS_FAILED;292}293if (!isEqual((JNIEnv *)env, watch.f_sig, watch.val, watches[i].val)) {294printf("(watch#%" PRIuPTR ") wrong new value: ", i);295printValue(watch.val, watch.f_sig);296printf(", expected: ");297printValue(watches[i].val, watch.f_sig);298printf("\n");299result = STATUS_FAILED;300}301return;302}303}304printf("Unexpected field modification catched: 0x%p\n", watch.fid);305result = STATUS_FAILED;306}307308#ifdef STATIC_BUILD309JNIEXPORT jint JNICALL Agent_OnLoad_fieldmod002(JavaVM *jvm, char *options, void *reserved) {310return Agent_Initialize(jvm, options, reserved);311}312JNIEXPORT jint JNICALL Agent_OnAttach_fieldmod002(JavaVM *jvm, char *options, void *reserved) {313return Agent_Initialize(jvm, options, reserved);314}315JNIEXPORT jint JNI_OnLoad_fieldmod002(JavaVM *jvm, char *options, void *reserved) {316return JNI_VERSION_1_8;317}318#endif319jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {320jvmtiError err;321jint res;322323if (options != NULL && strcmp(options, "printdump") == 0) {324printdump = JNI_TRUE;325}326327res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);328if (res != JNI_OK || jvmti == NULL) {329printf("Wrong result of a valid call to GetEnv!\n");330return JNI_ERR;331}332333err = jvmti->GetPotentialCapabilities(&caps);334if (err != JVMTI_ERROR_NONE) {335printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",336TranslateError(err), err);337return JNI_ERR;338}339340err = jvmti->AddCapabilities(&caps);341if (err != JVMTI_ERROR_NONE) {342printf("(AddCapabilities) unexpected error: %s (%d)\n",343TranslateError(err), err);344return JNI_ERR;345}346347err = jvmti->GetCapabilities(&caps);348if (err != JVMTI_ERROR_NONE) {349printf("(GetCapabilities) unexpected error: %s (%d)\n",350TranslateError(err), err);351return JNI_ERR;352}353354if (caps.can_generate_field_modification_events) {355callbacks.FieldModification = &FieldModification;356err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));357if (err != JVMTI_ERROR_NONE) {358printf("(SetEventCallbacks) unexpected error: %s (%d)\n",359TranslateError(err), err);360return JNI_ERR;361}362363err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,364JVMTI_EVENT_FIELD_MODIFICATION, NULL);365if (err != JVMTI_ERROR_NONE) {366printf("Failed to enable JVMTI_EVENT_FIELD_MODIFICATION: %s (%d)\n",367TranslateError(err), err);368return JNI_ERR;369}370} else {371printf("Warning: FieldModification watch is not implemented\n");372}373374return JNI_OK;375}376377JNIEXPORT void JNICALL378Java_nsk_jvmti_FieldModification_fieldmod002_getReady(JNIEnv *env, jclass clz) {379jvmtiError err;380jclass cls;381jmethodID ctor;382jintArray arr1, arr2;383jobject obj1, obj2;384size_t i;385386if (!caps.can_generate_field_modification_events) {387return;388}389390if (printdump == JNI_TRUE) {391printf(">>> setting field modification watches ...\n");392}393cls = env->FindClass("nsk/jvmti/FieldModification/fieldmod002a");394if (cls == NULL) {395printf("Cannot find fieldmod001a class!\n");396result = STATUS_FAILED;397return;398}399for (i = 0; i < sizeof(watches)/sizeof(watch_info); i++) {400if (watches[i].is_static == JNI_TRUE) {401watches[i].fid = env->GetStaticFieldID(402cls, watches[i].f_name, watches[i].f_sig);403} else {404watches[i].fid = env->GetFieldID(405cls, watches[i].f_name, watches[i].f_sig);406}407if (watches[i].fid == NULL) {408printf("Cannot get field ID for \"%s:%s\"\n",409watches[i].f_name, watches[i].f_sig);410result = STATUS_FAILED;411return;412}413err = jvmti->SetFieldModificationWatch(cls, watches[i].fid);414if (err == JVMTI_ERROR_NONE) {415eventsExpected++;416} else {417printf("(SetFieldModificationWatch#%" PRIuPTR ") unexpected error: %s (%d)\n",418i, TranslateError(err), err);419result = STATUS_FAILED;420}421}422423ctor = env->GetMethodID(cls, "<init>", "()V");424obj1 = env->NewGlobalRef(env->NewObject(cls, ctor));425obj2 = env->NewGlobalRef(env->NewObject(cls, ctor));426arr1 = (jintArray) env->NewGlobalRef(env->NewIntArray((jsize) 1));427arr2 = (jintArray) env->NewGlobalRef(env->NewIntArray((jsize) 1));428429watches[0].val.z = JNI_TRUE;430watches[1].val.b = 1;431watches[2].val.s = 2;432watches[3].val.i = 3;433watches[4].val.j = 4;434watches[5].val.f = 0.5F;435watches[6].val.d = 0.6;436watches[7].val.c = 0x7;437watches[8].val.l = obj1;438watches[9].val.l = arr1;439440watches[10].val.z = JNI_FALSE;441watches[11].val.b = 10;442watches[12].val.s = 20;443watches[13].val.i = 30;444watches[14].val.j = 40;445watches[15].val.f = 0.05F;446watches[16].val.d = 0.06;447watches[17].val.c = 0x70;448watches[18].val.l = obj2;449watches[19].val.l = arr2;450451if (printdump == JNI_TRUE) {452printf(">>> ... done\n");453}454}455456JNIEXPORT jint JNICALL457Java_nsk_jvmti_FieldModification_fieldmod002_check(JNIEnv *env,458jclass clz, jobject obj) {459jclass cls;460461if (!caps.can_generate_field_modification_events) {462return PASSED;463}464465if (printdump == JNI_TRUE) {466printf(">>> modifying fields ...\n");467}468469cls = env->FindClass("nsk/jvmti/FieldModification/fieldmod002a");470if (cls == NULL) {471printf("Cannot find fieldmod001a class!\n");472return STATUS_FAILED;473}474475env->SetStaticBooleanField(cls, watches[0].fid, watches[0].val.z);476env->SetStaticByteField(cls, watches[1].fid, watches[1].val.b);477env->SetStaticShortField(cls, watches[2].fid, watches[2].val.s);478env->SetStaticIntField(cls, watches[3].fid, watches[3].val.i);479env->SetStaticLongField(cls, watches[4].fid, watches[4].val.j);480env->SetStaticFloatField(cls, watches[5].fid, watches[5].val.f);481env->SetStaticDoubleField(cls, watches[6].fid, watches[6].val.d);482env->SetStaticCharField(cls, watches[7].fid, watches[7].val.c);483env->SetStaticObjectField(cls, watches[8].fid, watches[8].val.l);484env->SetStaticObjectField(cls, watches[9].fid, watches[9].val.l);485486env->SetBooleanField(obj, watches[10].fid, watches[10].val.z);487env->SetByteField(obj, watches[11].fid, watches[11].val.b);488env->SetShortField(obj, watches[12].fid, watches[12].val.s);489env->SetIntField(obj, watches[13].fid, watches[13].val.i);490env->SetLongField(obj, watches[14].fid, watches[14].val.j);491env->SetFloatField(obj, watches[15].fid, watches[15].val.f);492env->SetDoubleField(obj, watches[16].fid, watches[16].val.d);493env->SetCharField(obj, watches[17].fid, watches[17].val.c);494env->SetObjectField(obj, watches[18].fid, watches[18].val.l);495env->SetObjectField(obj, watches[19].fid, watches[19].val.l);496497if (printdump == JNI_TRUE) {498printf(">>> ... done\n");499}500501if (eventsCount != eventsExpected) {502printf("Wrong number of field modification events: %d, expected: %d\n",503eventsCount, eventsExpected);504result = STATUS_FAILED;505}506return result;507}508509}510511512