Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassPrepare/classprep001/classprep001.cpp
40951 views
/*1* Copyright (c) 2003, 2021, 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 23536#define EXP_STATUS (JVMTI_CLASS_STATUS_VERIFIED | JVMTI_CLASS_STATUS_PREPARED)3738typedef struct {39char *sig;40jint status;41jint mcount;42jint fcount;43jint icount;44} writable_class_info;4546typedef struct {47const char *sig;48jint status;49jint mcount;50jint fcount;51jint icount;52} class_info;5354static jvmtiEnv *jvmti = NULL;55static jvmtiEventCallbacks callbacks;56static jint result = PASSED;57static jboolean printdump = JNI_FALSE;58static size_t eventsCount = 0;59static size_t eventsExpected = 0;60static class_info classes[] = {61{ "Lnsk/jvmti/ClassPrepare/classprep001$TestInterface;", EXP_STATUS, 2, 1, 0 },62{ "Lnsk/jvmti/ClassPrepare/classprep001$TestClass;", EXP_STATUS, 3, 2, 1 }63};64// These classes are loaded on a different thread.65// We should not get ClassPrepare events for them.66static const class_info unexpectedClasses[] = {67{ "Lnsk/jvmti/ClassPrepare/classprep001$TestInterface2;", 0, 0, 0, 0 },68{ "Lnsk/jvmti/ClassPrepare/classprep001$TestClass2;", 0, 0, 0, 0}69};7071void printStatus(jint status) {72int flags = 0;73if ((status & JVMTI_CLASS_STATUS_VERIFIED) != 0) {74printf("JVMTI_CLASS_STATUS_VERIFIED");75flags++;76}77if ((status & JVMTI_CLASS_STATUS_PREPARED) != 0) {78if (flags > 0) printf(" | ");79printf("JVMTI_CLASS_STATUS_PREPARED");80flags++;81}82if ((status & JVMTI_CLASS_STATUS_INITIALIZED) != 0) {83if (flags > 0) printf(" | ");84printf("JVMTI_CLASS_STATUS_INITIALIZED");85flags++;86}87if ((status & JVMTI_CLASS_STATUS_ERROR) != 0) {88if (flags > 0) printf(" | ");89printf("JVMTI_CLASS_STATUS_ERROR");90flags++;91}92printf(" (0x%x)\n", status);93}9495const size_t NOT_FOUND = (size_t)(-1);9697size_t findClass(const char *classSig, const class_info *arr, int size) {98for (int i = 0; i < size; i++) {99if (strcmp(classSig, arr[i].sig) == 0) {100return i;101}102}103return NOT_FOUND;104}105106void JNICALL ClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *env,107jthread thr, jclass cls) {108jvmtiError err;109writable_class_info inf;110jmethodID *methods;111jfieldID *fields;112jclass *interfaces;113char *name, *sig, *generic;114int i;115116err = jvmti_env->GetClassSignature(cls, &inf.sig, &generic);117if (err != JVMTI_ERROR_NONE) {118printf("(GetClassSignature#%" PRIuPTR ") unexpected error: %s (%d)\n",119eventsCount, TranslateError(err), err);120result = STATUS_FAILED;121return;122}123err = jvmti_env->GetClassStatus(cls, &inf.status);124if (err != JVMTI_ERROR_NONE) {125printf("(GetClassStatus#%" PRIuPTR ") unexpected error: %s (%d)\n",126eventsCount, TranslateError(err), err);127result = STATUS_FAILED;128}129err = jvmti_env->GetClassMethods(cls, &inf.mcount, &methods);130if (err != JVMTI_ERROR_NONE) {131printf("(GetClassMethods#%" PRIuPTR ") unexpected error: %s (%d)\n",132eventsCount, TranslateError(err), err);133result = STATUS_FAILED;134return;135}136err = jvmti_env->GetClassFields(cls, &inf.fcount, &fields);137if (err != JVMTI_ERROR_NONE) {138printf("(GetClassMethods#%" PRIuPTR ") unexpected error: %s (%d)\n",139eventsCount, TranslateError(err), err);140result = STATUS_FAILED;141return;142}143err = jvmti_env->GetImplementedInterfaces(cls,144&inf.icount, &interfaces);145if (err != JVMTI_ERROR_NONE) {146printf("(GetImplementedInterfaces#%" PRIuPTR ") unexpected error: %s (%d)\n",147eventsCount, TranslateError(err), err);148result = STATUS_FAILED;149return;150}151152if (printdump == JNI_TRUE) {153printf(">>> [class prepare event #%" PRIuPTR "]", eventsCount);154printf(" \"%s\"\n", inf.sig);155printf(">>> status: ");156printStatus(inf.status);157printf(">>> %d methods:", inf.mcount);158for (i = 0; i < inf.mcount; i++) {159if (i > 0) printf(",");160if (methods[i] == NULL) {161printf(" null");162} else {163err = jvmti_env->GetMethodName(methods[i],164&name, &sig, &generic);165if (err == JVMTI_ERROR_NONE) {166printf(" \"%s%s\"", name, sig);167} else {168printf(" ???");169}170}171}172printf("\n");173printf(">>> %d fields:", inf.fcount);174for (i = 0; i < inf.fcount; i++) {175if (i > 0) printf(",");176if (fields[i] == NULL) {177printf(" null");178} else {179err = jvmti_env->GetFieldName(cls, fields[i],180&name, &sig, &generic);181if (err == JVMTI_ERROR_NONE) {182printf(" \"%s, %s\"", name, sig);183} else {184printf(" ???");185}186}187}188printf("\n");189printf(">>> %d interfaces:", inf.icount);190for (i = 0; i < inf.icount; i++) {191if (i > 0) printf(",");192if (interfaces[i] == NULL) {193printf(" null");194} else {195err = jvmti_env->GetClassSignature(196interfaces[i], &sig, &generic);197if (err == JVMTI_ERROR_NONE) {198printf(" \"%s\"", sig);199} else {200printf(" ???");201}202}203}204printf("\n");205}206207size_t expectedClassIdx = findClass(inf.sig, classes, sizeof(classes)/sizeof(class_info));208// Test classes loading may cause system classes loading - skip them.209if (expectedClassIdx == NOT_FOUND) {210size_t unexpectedClassIdx = findClass(inf.sig, unexpectedClasses,211sizeof(unexpectedClasses)/sizeof(class_info));212if (unexpectedClassIdx != NOT_FOUND) {213printf("# wrong class: \"%s\"\n", inf.sig);214result = STATUS_FAILED;215}216return;217}218219if (eventsCount != expectedClassIdx) {220printf("(#%" PRIuPTR ") unexpected order: %" PRIuPTR ", expected: %" PRIuPTR "\n",221eventsCount, expectedClassIdx, eventsCount);222result = STATUS_FAILED;223return;224}225226if (inf.status != classes[eventsCount].status) {227printf("(#%" PRIuPTR ") wrong status: ", eventsCount);228printStatus(inf.status);229printf(" expected: ");230printStatus(classes[eventsCount].status);231result = STATUS_FAILED;232}233if (inf.mcount != classes[eventsCount].mcount) {234printf("(#%" PRIuPTR ") wrong number of methods: 0x%x",235eventsCount, inf.mcount);236printf(", expected: 0x%x\n", classes[eventsCount].mcount);237result = STATUS_FAILED;238}239if (inf.fcount != classes[eventsCount].fcount) {240printf("(#%" PRIuPTR ") wrong number of fields: 0x%x",241eventsCount, inf.fcount);242printf(", expected: 0x%x\n", classes[eventsCount].fcount);243result = STATUS_FAILED;244}245if (inf.icount != classes[eventsCount].icount) {246printf("(#%" PRIuPTR ") wrong number of interfaces: 0x%x",247eventsCount, inf.icount);248printf(", expected: 0x%x\n", classes[eventsCount].icount);249result = STATUS_FAILED;250}251eventsCount++;252}253254#ifdef STATIC_BUILD255JNIEXPORT jint JNICALL Agent_OnLoad_classprep001(JavaVM *jvm, char *options, void *reserved) {256return Agent_Initialize(jvm, options, reserved);257}258JNIEXPORT jint JNICALL Agent_OnAttach_classprep001(JavaVM *jvm, char *options, void *reserved) {259return Agent_Initialize(jvm, options, reserved);260}261JNIEXPORT jint JNI_OnLoad_classprep001(JavaVM *jvm, char *options, void *reserved) {262return JNI_VERSION_1_8;263}264#endif265jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {266jvmtiError err;267jint res;268269if (options != NULL && strcmp(options, "printdump") == 0) {270printdump = JNI_TRUE;271}272273res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);274if (res != JNI_OK || jvmti == NULL) {275printf("Wrong result of a valid call to GetEnv!\n");276return JNI_ERR;277}278279callbacks.ClassPrepare = &ClassPrepare;280err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));281if (err != JVMTI_ERROR_NONE) {282printf("(SetEventCallbacks) unexpected error: %s (%d)\n",283TranslateError(err), err);284return JNI_ERR;285}286287return JNI_OK;288}289290JNIEXPORT void JNICALL291Java_nsk_jvmti_ClassPrepare_classprep001_getReady(JNIEnv *env, jclass cls, jthread thread) {292jvmtiError err;293294if (jvmti == NULL) {295printf("JVMTI client was not properly loaded!\n");296return;297}298299err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,300JVMTI_EVENT_CLASS_PREPARE, thread);301if (err == JVMTI_ERROR_NONE) {302eventsExpected = sizeof(classes)/sizeof(class_info);303} else {304printf("Failed to enable JVMTI_EVENT_CLASS_PREPARE: %s (%d)\n",305TranslateError(err), err);306result = STATUS_FAILED;307}308}309310JNIEXPORT jint JNICALL311Java_nsk_jvmti_ClassPrepare_classprep001_check(JNIEnv *env, jclass cls, jthread thread) {312jvmtiError err;313314if (jvmti == NULL) {315printf("JVMTI client was not properly loaded!\n");316return STATUS_FAILED;317}318319err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,320JVMTI_EVENT_CLASS_PREPARE, thread);321if (err != JVMTI_ERROR_NONE) {322printf("Failed to disable JVMTI_EVENT_CLASS_PREPARE: %s (%d)\n",323TranslateError(err), err);324result = STATUS_FAILED;325}326327if (eventsCount != eventsExpected) {328printf("Wrong number of class prepare events: %" PRIuPTR ", expected: %" PRIuPTR "\n",329eventsCount, eventsExpected);330result = STATUS_FAILED;331}332return result;333}334335}336337338