Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassFileLoadHook/classfloadhk007/classfloadhk007.cpp
40955 views
1
/*
2
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
#include <string.h>
25
#include "jvmti.h"
26
#include "agent_common.h"
27
#include "jni_tools.h"
28
#include "jvmti_tools.h"
29
30
extern "C" {
31
32
/* ============================================================================= */
33
34
/* scaffold objects */
35
static jlong timeout = 0;
36
37
/* constant names */
38
#define DEBUGEE_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk007"
39
#define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk007r"
40
#define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";"
41
#define TESTED_CLASSLOADER_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk007ClassLoader"
42
#define TESTED_CLASSLOADER_SIG "L" TESTED_CLASSLOADER_NAME ";"
43
44
#define BYTECODE_FIELD_SIG "[B"
45
#define REDEF_BYTECODE_FIELD_NAME "redefClassBytes"
46
47
#define CLASSLOADER_FIELD_NAME "classLoader"
48
#define TESTED_CLASS_FIELD_NAME "testedClass"
49
#define TESTED_CLASS_FIELD_SIG "Ljava/lang/Class;"
50
51
static jobject classLoader = NULL;
52
static jclass testedClass = NULL;
53
54
static jint redefClassSize = 0;
55
static unsigned char* redefClassBytes = NULL;
56
57
static volatile int eventsCount = 0;
58
59
/* ============================================================================= */
60
61
/** Check (strictly or not) if bytecode has expected size and bytes or complain an error. */
62
static int checkBytecode(const char kind[], jint size, const unsigned char bytes[],
63
jint expectedSize, const unsigned char expectedBytes[],
64
int strict) {
65
int success = NSK_TRUE;
66
67
NSK_DISPLAY3("Check %s bytecode: 0x%p:%d\n", kind, (void*)bytes, (int)size);
68
if (nsk_getVerboseMode()) {
69
nsk_printHexBytes(" ", 16, size, bytes);
70
}
71
72
if (bytes == NULL) {
73
NSK_COMPLAIN2("Unexpected NULL pointer to %s bytecode in CLASS_FILE_LOAD_HOOK: 0x%p\n",
74
kind, (void*)bytes);
75
return NSK_FALSE;
76
}
77
78
if (size <= 0) {
79
NSK_COMPLAIN2("Unexpected zero size of %s bytecode in CLASS_FILE_LOAD_HOOK: %d\n",
80
kind, (int)size);
81
return NSK_FALSE;
82
}
83
84
if (strict) {
85
if (size != expectedSize) {
86
NSK_COMPLAIN3("Unexpected size of %s bytecode in CLASS_FILE_LOAD_HOOK:\n"
87
"# got size: %d\n"
88
"# expected: %d\n",
89
kind, (int)size, (int)expectedSize);
90
success = NSK_FALSE;
91
} else {
92
jint different = 0;
93
jint i;
94
95
for (i = 0; i < size; i++) {
96
if (bytes[i] != expectedBytes[i]) {
97
different++;
98
}
99
}
100
if (different > 0) {
101
NSK_COMPLAIN2("Unexpected bytes in %s bytecode in CLASS_FILE_LOAD_HOOK:\n"
102
"# different bytes: %d\n"
103
"# total bytes: %d\n",
104
(int)different, (int)size);
105
success = NSK_FALSE;
106
}
107
}
108
109
if (!success) {
110
NSK_COMPLAIN2("Got %s bytecode is not equal to expected bytecode: %d bytes\n",
111
kind, expectedSize);
112
if (nsk_getVerboseMode()) {
113
nsk_printHexBytes(" ", 16, expectedSize, expectedBytes);
114
}
115
} else {
116
NSK_DISPLAY1("All %s bytecode is equal to expected one\n", kind);
117
}
118
}
119
120
return success;
121
}
122
123
/** Get classfile bytecode from a static field of given class. */
124
static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,
125
const char fieldName[], const char fieldSig[],
126
jint* size, unsigned char* *bytes) {
127
128
jfieldID fieldID = NULL;
129
jbyteArray array = NULL;
130
jbyte* elements;
131
int i;
132
133
NSK_DISPLAY1("Find static field: %s\n", fieldName);
134
if (!NSK_JNI_VERIFY(jni, (fieldID =
135
jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {
136
nsk_jvmti_setFailStatus();
137
return NSK_FALSE;
138
}
139
NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);
140
141
NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName);
142
if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray)
143
jni->GetStaticObjectField(cls, fieldID)) != NULL)) {
144
nsk_jvmti_setFailStatus();
145
return NSK_FALSE;
146
}
147
NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array);
148
149
if (!NSK_JNI_VERIFY(jni, (*size = jni->GetArrayLength(array)) > 0)) {
150
nsk_jvmti_setFailStatus();
151
return NSK_FALSE;
152
}
153
NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size);
154
155
{
156
jboolean isCopy;
157
if (!NSK_JNI_VERIFY(jni, (elements = jni->GetByteArrayElements(array, &isCopy)) != NULL)) {
158
nsk_jvmti_setFailStatus();
159
return NSK_FALSE;
160
}
161
}
162
NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements);
163
164
if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*size, bytes))) {
165
nsk_jvmti_setFailStatus();
166
return NSK_FALSE;
167
}
168
NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes);
169
170
for (i = 0; i < *size; i++) {
171
(*bytes)[i] = (unsigned char)elements[i];
172
}
173
NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size);
174
175
NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements);
176
NSK_TRACE(jni->ReleaseByteArrayElements(array, elements, JNI_ABORT));
177
NSK_DISPLAY0(" ... released\n");
178
179
return NSK_TRUE;
180
}
181
182
/** Get global reference to object from a static field of given class. */
183
static jobject getObject(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls,
184
const char fieldName[], const char fieldSig[]) {
185
186
jfieldID fieldID = NULL;
187
jobject obj = NULL;
188
189
NSK_DISPLAY1("Find static field: %s\n", fieldName);
190
if (!NSK_JNI_VERIFY(jni, (fieldID =
191
jni->GetStaticFieldID(cls, fieldName, fieldSig)) != NULL)) {
192
nsk_jvmti_setFailStatus();
193
return NULL;
194
}
195
NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID);
196
197
NSK_DISPLAY1("Get object from static field: %s\n", fieldName);
198
if (!NSK_JNI_VERIFY(jni, (obj = jni->GetStaticObjectField(cls, fieldID)) != NULL)) {
199
nsk_jvmti_setFailStatus();
200
return NULL;
201
}
202
NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)obj);
203
204
NSK_DISPLAY1("Make global reference to object: 0x%p\n", obj);
205
if (!NSK_JNI_VERIFY(jni, (obj = jni->NewGlobalRef(obj)) != NULL)) {
206
nsk_jvmti_setFailStatus();
207
return NULL;
208
}
209
NSK_DISPLAY1(" ... got global ref: 0x%p\n", (void*)obj);
210
211
return obj;
212
}
213
214
/** Redefine given class with new bytecode. */
215
static int redefineClass(jvmtiEnv* jvmti, jclass klass, const char className[],
216
jint size, unsigned char bytes[]) {
217
jvmtiClassDefinition classDef;
218
219
classDef.klass = klass;
220
classDef.class_byte_count = size;
221
classDef.class_bytes = bytes;
222
223
NSK_DISPLAY1("Redefine class: %s\n", className);
224
if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {
225
nsk_jvmti_setFailStatus();
226
return NSK_FALSE;
227
}
228
NSK_DISPLAY1(" ... redefined with bytecode: %d bytes\n", (int)size);
229
230
return NSK_TRUE;
231
}
232
233
/* ============================================================================= */
234
235
/** Agent algorithm. */
236
static void JNICALL
237
agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
238
NSK_DISPLAY0("Wait for debuggee to load original class\n");
239
if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
240
return;
241
242
/* perform testing */
243
{
244
{
245
jclass debugeeClass = NULL;
246
247
NSK_DISPLAY0(">>> Obtain debuggee class\n");
248
NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
249
if (!NSK_JNI_VERIFY(jni, (debugeeClass =
250
jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {
251
nsk_jvmti_setFailStatus();
252
return;
253
}
254
NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);
255
256
NSK_DISPLAY0(">>> Obtain tested class object\n");
257
if (!NSK_VERIFY((testedClass = (jclass)
258
getObject(jvmti, jni, debugeeClass, TESTED_CLASS_FIELD_NAME,
259
TESTED_CLASS_FIELD_SIG)) != NULL))
260
return;
261
262
NSK_DISPLAY0(">>> Obtain classloader object\n");
263
if (!NSK_VERIFY((classLoader =
264
getObject(jvmti, jni, debugeeClass, CLASSLOADER_FIELD_NAME,
265
TESTED_CLASSLOADER_SIG)) != NULL))
266
return;
267
268
NSK_DISPLAY0(">>> Obtain redefined bytecode of tested class\n");
269
if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass,
270
REDEF_BYTECODE_FIELD_NAME,
271
BYTECODE_FIELD_SIG,
272
&redefClassSize, &redefClassBytes)))
273
return;
274
}
275
276
NSK_DISPLAY0(">>> Redefine tested class\n");
277
{
278
if (!NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,
279
redefClassSize, redefClassBytes)))
280
return;
281
}
282
283
NSK_DISPLAY0(">>> Testcase #1: Redefine class and check CLASS_FILE_LOAD_HOOK event\n");
284
{
285
jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
286
287
NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK");
288
if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))
289
return;
290
NSK_DISPLAY0(" ... event enabled\n");
291
292
NSK_VERIFY(redefineClass(jvmti, testedClass, TESTED_CLASS_NAME,
293
redefClassSize, redefClassBytes));
294
295
NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK");
296
if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {
297
NSK_DISPLAY0(" ... event disabled\n");
298
}
299
300
NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK");
301
if (eventsCount != 1) {
302
NSK_COMPLAIN3("Unexpected number of %s events received for tested class:\n"
303
"# received: %d events\n"
304
"# expected: %d events\n",
305
"CLASS_FILE_LOAD_HOOK", eventsCount, 1);
306
nsk_jvmti_setFailStatus();
307
} else {
308
NSK_DISPLAY1(" ... received: %d events\n", eventsCount);
309
}
310
}
311
312
NSK_DISPLAY0(">>> Clean used data\n");
313
{
314
NSK_DISPLAY1("Delete global reference to classloader object: 0x%p\n", (void*)classLoader);
315
jni->DeleteGlobalRef(classLoader);
316
317
NSK_DISPLAY1("Delete global reference to tested class object: 0x%p\n", (void*)testedClass);
318
jni->DeleteGlobalRef(testedClass);
319
320
NSK_DISPLAY1("Deallocate redefined bytecode array: 0x%p\n", (void*)redefClassBytes);
321
if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(redefClassBytes))) {
322
nsk_jvmti_setFailStatus();
323
}
324
}
325
}
326
327
NSK_DISPLAY0("Let debugee to finish\n");
328
if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
329
return;
330
}
331
332
/* ============================================================================= */
333
334
/** Callback for CLASS_FILE_LOAD_HOOK event **/
335
static void JNICALL
336
callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni,
337
jclass class_being_redefined,
338
jobject loader, const char* name, jobject protection_domain,
339
jint class_data_len, const unsigned char* class_data,
340
jint *new_class_data_len, unsigned char** new_class_data) {
341
342
NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n",
343
nsk_null_string(name), (void*)loader, (void*)class_being_redefined,
344
(void*)class_data, (int)class_data_len);
345
346
if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) {
347
NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME);
348
eventsCount++;
349
350
NSK_DISPLAY1("Check classloader: 0x%p\n", (void*)loader);
351
if (loader == NULL) {
352
NSK_COMPLAIN1("Unexpected NULL classloader in CLASS_FILE_LOAD_HOOK: 0x%p\n",
353
(void*)loader);
354
nsk_jvmti_setFailStatus();
355
} else if (!jni->IsSameObject(loader, classLoader)) {
356
NSK_COMPLAIN2("Unexpected classloader in CLASS_FILE_LOAD_HOOK:\n"
357
"# got classloder: 0x%p\n"
358
"# expected same as: 0x%p\n",
359
(void*)loader, (void*)classLoader);
360
nsk_jvmti_setFailStatus();
361
}
362
363
NSK_DISPLAY1("Check class_being_redefined: 0x%p\n", (void*)class_being_redefined);
364
if (class_being_redefined == NULL) {
365
NSK_COMPLAIN1("Unexpected NULL class_being_redefined in CLASS_FILE_LOAD_HOOK: 0x%p\n",
366
(void*)class_being_redefined);
367
nsk_jvmti_setFailStatus();
368
} else if (!jni->IsSameObject(class_being_redefined, testedClass)) {
369
NSK_COMPLAIN2("Unexpected class_being_redefined in CLASS_FILE_LOAD_HOOK:\n"
370
"# got class: 0x%p\n"
371
"# expected same as: 0x%p\n",
372
(void*)class_being_redefined, (void*)testedClass);
373
nsk_jvmti_setFailStatus();
374
}
375
376
if (!checkBytecode("redefined", class_data_len, class_data,
377
redefClassSize, redefClassBytes, NSK_TRUE)) {
378
nsk_jvmti_setFailStatus();
379
}
380
}
381
}
382
383
/* ============================================================================= */
384
385
/** Agent library initialization. */
386
#ifdef STATIC_BUILD
387
JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {
388
return Agent_Initialize(jvm, options, reserved);
389
}
390
JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {
391
return Agent_Initialize(jvm, options, reserved);
392
}
393
JNIEXPORT jint JNI_OnLoad_classfloadhk007(JavaVM *jvm, char *options, void *reserved) {
394
return JNI_VERSION_1_8;
395
}
396
#endif
397
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
398
jvmtiEnv* jvmti = NULL;
399
400
/* init framework and parse options */
401
if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
402
return JNI_ERR;
403
404
timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
405
406
/* create JVMTI environment */
407
if (!NSK_VERIFY((jvmti =
408
nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
409
return JNI_ERR;
410
411
NSK_DISPLAY1("Add required capabilities: %s\n", "can_generate_eraly_class_hook_events, can_redefine_classes");
412
{
413
jvmtiCapabilities caps;
414
415
memset(&caps, 0, sizeof(caps));
416
caps.can_generate_all_class_hook_events = 1;
417
caps.can_redefine_classes = 1;
418
if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
419
return JNI_ERR;
420
}
421
}
422
NSK_DISPLAY0(" ... added\n");
423
424
NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK");
425
{
426
jvmtiEventCallbacks callbacks;
427
jint size = (jint)sizeof(callbacks);
428
429
memset(&callbacks, 0, sizeof(callbacks));
430
callbacks.ClassFileLoadHook = callbackClassFileLoadHook;
431
if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) {
432
return JNI_ERR;
433
}
434
}
435
NSK_DISPLAY0(" ... set\n");
436
437
/* register agent proc and arg */
438
if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
439
return JNI_ERR;
440
441
return JNI_OK;
442
}
443
444
/* ============================================================================= */
445
446
}
447
448