Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/libHiddenClassSigTest.cpp
41155 views
1
/*
2
* Copyright (c) 2019, 2020, 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
27
extern "C" {
28
29
static const char* EXP_INTERF_SIG = "LP/Q/HCInterf;";
30
static const char* SIG_START = "LP/Q/HiddenClassSig";
31
static const size_t SIG_START_LEN = strlen(SIG_START);
32
static const int ACC_INTERFACE = 0x0200; // Interface class modifiers bit
33
34
static jvmtiEnv *jvmti = NULL;
35
static jint class_load_count = 0;
36
static jint class_prep_count = 0;
37
static bool failed = false;
38
39
#define LOG0(str) { printf(str); fflush(stdout); }
40
#define LOG1(str, arg) { printf(str, arg); fflush(stdout); }
41
#define LOG2(str, arg1, arg2) { printf(str, arg1, arg2); fflush(stdout); }
42
43
#define CHECK_JVMTI_ERROR(jni, err, msg) \
44
if (err != JVMTI_ERROR_NONE) { \
45
LOG1("CHECK_JVMTI_ERROR: JVMTI function returned error: %d\n", err); \
46
jni->FatalError(msg); \
47
return; \
48
}
49
50
/* Return the jmethodID of j.l.Class.isHidden() method. */
51
static jmethodID
52
is_hidden_mid(JNIEnv* jni) {
53
char* csig = NULL;
54
jint count = 0;
55
jmethodID *methods = NULL;
56
jclass clazz = jni->FindClass("java/lang/Class");
57
if (clazz == NULL) {
58
jni->FatalError("is_hidden_mid: Error: FindClass returned NULL for java/lang/Class\n");
59
return NULL;
60
}
61
62
// find the jmethodID of j.l.Class.isHidden() method
63
jmethodID mid = jni->GetMethodID(clazz, "isHidden", "()Z");
64
if (mid == NULL) {
65
jni->FatalError("is_hidden_mid: Error in jni GetMethodID: Cannot find j.l.Class.isHidden method\n");
66
}
67
return mid;
68
}
69
70
/* Return true if the klass is hidden. */
71
static bool
72
is_hidden(JNIEnv* jni, jclass klass) {
73
static jmethodID is_hid_mid = NULL;
74
75
if (is_hid_mid == NULL) {
76
is_hid_mid = is_hidden_mid(jni);
77
}
78
// invoke j.l.Class.isHidden() method
79
bool res = jni->CallBooleanMethod(klass, is_hid_mid);
80
if (jni->ExceptionCheck()) {
81
jni->ExceptionDescribe();
82
jni->FatalError("is_hidden: Exception in jni CallBooleanMethod\n");
83
}
84
return res;
85
}
86
87
/* Check the class signature matches the expected. */
88
static void
89
check_class_signature(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass, bool is_hidden, const char* exp_sig) {
90
jint class_modifiers = 0;
91
char* sig = NULL;
92
char* gsig = NULL;
93
jvmtiError err;
94
95
// get class signature
96
err = jvmti->GetClassSignature(klass, &sig, &gsig);
97
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class: Error in JVMTI GetClassSignature");
98
99
LOG1("check_class_signature: class with sig: %s\n", sig);
100
LOG1("check_class_signature: class with gsig: %s\n", gsig);
101
102
if (strcmp(sig, exp_sig) != 0) {
103
LOG2("check_class_signature: FAIL: Hidden class signature %s does not match expected: %s\n", sig, exp_sig);
104
failed = true;
105
}
106
if (is_hidden && gsig == NULL) {
107
LOG0("check_class_signature: FAIL: unexpected NULL generic signature for hidden class\n");
108
failed = true;
109
}
110
}
111
112
/* Test hidden class flags: it should not be interface, array nor modifiable. */
113
static void
114
check_hidden_class_flags(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass) {
115
jint modifiers = 0;
116
jboolean flag = false;
117
jvmtiError err;
118
119
err = jvmti->GetClassModifiers(klass, &modifiers);
120
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_flags: Error in JVMTI GetClassModifiers");
121
LOG1("check_hidden_class_flags: hidden class modifiers: 0x%x\n", modifiers);
122
if ((modifiers & ACC_INTERFACE) != 0) {
123
LOG0("check_hidden_class_flags: FAIL: unexpected ACC_INTERFACE bit in hidden class modifiers\n");
124
failed = true;
125
return;
126
}
127
128
err = jvmti->IsInterface(klass, &flag);
129
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_flags: Error in JVMTI IsInterface");
130
if (flag) {
131
LOG0("check_hidden_class_flags: FAIL: hidden class is not expected to be interface\n");
132
failed = true;
133
return;
134
}
135
136
err = jvmti->IsArrayClass(klass, &flag);
137
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_flags: Error in JVMTI IsArrayClass");
138
if (flag) {
139
LOG0("check_hidden_class_flags: FAIL: hidden class is not expected to be array\n");
140
failed = true;
141
return;
142
}
143
err = jvmti->IsModifiableClass(klass, &flag);
144
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_flags: Error in JVMTI IsModifiableClass");
145
if (flag) {
146
LOG0("check_hidden_class_flags: FAIL: hidden class is not expected to be modifiable\n");
147
failed = true;
148
}
149
}
150
151
/* Test GetClassLoaderClasses: it should not return any hidden classes. */
152
static void
153
check_hidden_class_loader(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass) {
154
jint count = 0;
155
jobject loader = NULL;
156
jclass* loader_classes = NULL;
157
jboolean found = false;
158
jvmtiError err;
159
160
err = jvmti->GetClassLoader(klass, &loader);
161
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_loader: Error in JVMTI GetClassLoader");
162
163
jni->EnsureLocalCapacity(256); // to avoid warnings: JNI local refs NN exceeds capacity
164
165
err = jvmti->GetClassLoaderClasses(loader, &count, &loader_classes);
166
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_loader: Error in JVMTI GetClassLoaderClasses");
167
168
for (int idx = 0; idx < count; idx++) {
169
char* sig = NULL;
170
jclass kls = loader_classes[idx];
171
172
// GetClassLoaderClasses should not return any hidden classes
173
if (!is_hidden(jni, kls)) {
174
continue;
175
}
176
// get class signature
177
err = jvmti->GetClassSignature(kls, &sig, NULL);
178
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_loader: Error in JVMTI GetClassSignature");
179
180
LOG1("check_hidden_class_loader: FAIL: JVMTI GetClassLoaderClasses returned hidden class: %s\n", sig);
181
failed = true;
182
return;
183
}
184
LOG0("check_hidden_class_loader: not found hidden class in its loader classes as expected\n");
185
}
186
187
/* Test the hidden class implements expected interface. */
188
static void
189
check_hidden_class_impl_interf(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass) {
190
char* sig = NULL;
191
jint count = 0;
192
jclass* interfaces = NULL;
193
jvmtiError err;
194
195
// check that hidden class implements just one interface
196
err = jvmti->GetImplementedInterfaces(klass, &count, &interfaces);
197
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_impl_interf: Error in JVMTI GetImplementedInterfaces");
198
if (count != 1) {
199
LOG1("check_hidden_class_impl_interf: FAIL: implemented interfaces count: %d, expected to be 1\n", count);
200
failed = true;
201
return;
202
}
203
// get interface signature
204
err = jvmti->GetClassSignature(interfaces[0], &sig, NULL);
205
CHECK_JVMTI_ERROR(jni, err, "check_hidden_class_impl_interf: Error in JVMTI GetClassSignature for implemented interface");
206
207
// check the interface signature is matching the expected
208
if (strcmp(sig, EXP_INTERF_SIG) != 0) {
209
LOG2("check_hidden_class_impl_interf: FAIL: implemented interface signature: %s, expected to be: %s\n",
210
sig, EXP_INTERF_SIG);
211
failed = true;
212
}
213
}
214
215
/* Test hidden class. */
216
static void
217
check_hidden_class(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass, const char* exp_sig) {
218
char* source_file_name = NULL;
219
220
LOG1("\n### Native agent: check_hidden_class started: class: %s\n", exp_sig);
221
222
check_class_signature(jvmti, jni, klass, true /* not hidden */, exp_sig);
223
if (failed) return;
224
225
check_hidden_class_flags(jvmti, jni, klass);
226
if (failed) return;
227
228
check_hidden_class_loader(jvmti, jni, klass);
229
if (failed) return;
230
231
check_hidden_class_impl_interf(jvmti, jni, klass);
232
if (failed) return;
233
234
LOG0("### Native agent: check_hidden_class finished\n");
235
}
236
237
/* Test hidden class array. */
238
static void
239
check_hidden_class_array(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass_array, const char* exp_sig) {
240
char* source_file_name = NULL;
241
242
LOG1("\n### Native agent: check_hidden_class_array started: array: %s\n", exp_sig);
243
244
check_class_signature(jvmti, jni, klass_array, false /* is hidden */, exp_sig);
245
if (failed) return;
246
247
LOG0("### Native agent: check_hidden_class_array finished\n");
248
}
249
250
/* Process a CLASS_LOAD or aClassPrepare event. */
251
static void process_class_event(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass,
252
jint* event_count_ptr, const char* event_name) {
253
char* sig = NULL;
254
char* gsig = NULL;
255
jvmtiError err;
256
257
// get class signature
258
err = jvmti->GetClassSignature(klass, &sig, &gsig);
259
CHECK_JVMTI_ERROR(jni, err, "ClassLoad event: Error in JVMTI GetClassSignature");
260
261
// check if this is an expected class event for hidden class
262
if (strlen(sig) > strlen(SIG_START) &&
263
strncmp(sig, SIG_START, SIG_START_LEN) == 0 &&
264
is_hidden(jni, klass)) {
265
(*event_count_ptr)++;
266
if (gsig == NULL) {
267
LOG1("%s event: FAIL: GetClassSignature returned NULL generic signature for hidden class\n", event_name);
268
failed = true;
269
}
270
LOG2("%s event: hidden class with sig: %s\n", event_name, sig);
271
LOG2("%s event: hidden class with gsig: %s\n", event_name, gsig);
272
}
273
}
274
275
/* Check CLASS_LOAD event is generated for the given hidden class. */
276
static void JNICALL
277
ClassLoad(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jclass klass) {
278
process_class_event(jvmti, jni, klass, &class_load_count, "ClassLoad");
279
}
280
281
/* Check CLASS_PREPARE event is generated for the given hidden class. */
282
static void JNICALL
283
ClassPrepare(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jclass klass) {
284
process_class_event(jvmti, jni, klass, &class_prep_count, "ClassPrepare");
285
}
286
287
/* Enable CLASS_LOAD event notification mode. */
288
static void JNICALL
289
VMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
290
jvmtiError err;
291
292
printf("VMInit event: SIG_START: %s, SIG_START_LEN: %d\n", SIG_START, (int)SIG_START_LEN);
293
fflush(stdout);
294
295
// enable ClassLoad event notification mode
296
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL);
297
CHECK_JVMTI_ERROR(jni, err, "VMInit event: Error in enabling ClassLoad events notification");
298
299
// enable ClassPrepare event notification mode
300
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
301
CHECK_JVMTI_ERROR(jni, err, "VMInit event: Error in enabling ClassPrepare events notification");
302
}
303
304
JNIEXPORT jint JNICALL
305
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
306
jvmtiEventCallbacks callbacks;
307
jvmtiError err;
308
309
LOG0("Agent_OnLoad: started\n");
310
if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
311
LOG0("Agent_OnLoad: Error in GetEnv in obtaining jvmtiEnv*\n");
312
failed = true;
313
return JNI_ERR;
314
}
315
316
// set required event callbacks
317
memset(&callbacks, 0, sizeof(callbacks));
318
callbacks.ClassLoad = &ClassLoad;
319
callbacks.ClassPrepare = &ClassPrepare;
320
callbacks.VMInit = &VMInit;
321
322
err = jvmti->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
323
if (err != JVMTI_ERROR_NONE) {
324
LOG1("Agent_OnLoad: Error in JVMTI SetEventCallbacks: %d\n", err);
325
failed = true;
326
return JNI_ERR;
327
}
328
329
// enable VM_INIT event notification mode
330
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
331
if (err != JVMTI_ERROR_NONE) {
332
LOG1("Agent_OnLoad: Error in JVMTI SetEventNotificationMode: %d\n", err);
333
failed = true;
334
return JNI_ERR;
335
}
336
337
LOG0("Agent_OnLoad: finished\n");
338
return JNI_OK;
339
}
340
341
/* Native method: checkHiddenClass(). */
342
JNIEXPORT void JNICALL
343
Java_P_Q_HiddenClassSigTest_checkHiddenClass(JNIEnv *jni, jclass klass, jclass hidden_klass, jstring exp_sig_str) {
344
const char* exp_sig = jni->GetStringUTFChars(exp_sig_str, NULL);
345
346
if (exp_sig == NULL) {
347
jni->FatalError("check_hidden_class: Error: JNI GetStringChars returned NULL for jstring\n");
348
return;
349
}
350
check_hidden_class(jvmti, jni, hidden_klass, exp_sig);
351
352
jni->ReleaseStringUTFChars(exp_sig_str, exp_sig);
353
}
354
355
/* Native method: checkHiddenClassArray(). */
356
JNIEXPORT void JNICALL
357
Java_P_Q_HiddenClassSigTest_checkHiddenClassArray(JNIEnv *jni, jclass klass, jclass hidden_klass_array, jstring exp_sig_str) {
358
const char* exp_sig = jni->GetStringUTFChars(exp_sig_str, NULL);
359
360
if (exp_sig == NULL) {
361
jni->FatalError("check_hidden_class_array: Error: JNI GetStringChars returned NULL for jstring\n");
362
return;
363
}
364
check_hidden_class_array(jvmti, jni, hidden_klass_array, exp_sig);
365
366
jni->ReleaseStringUTFChars(exp_sig_str, exp_sig);
367
}
368
369
/* Native method: checkFailed(). */
370
JNIEXPORT jboolean JNICALL
371
Java_P_Q_HiddenClassSigTest_checkFailed(JNIEnv *jni, jclass klass) {
372
if (class_load_count == 0) {
373
// expected ClassLoad event was not generated for hidden class
374
LOG0("Native Agent: FAIL: missed ClassLoad event for hidden class\n");
375
failed = true;
376
}
377
if (class_prep_count == 0) {
378
// expected ClassPrepare event was not generated for hidden class
379
LOG0("Native Agent: FAIL: missed ClassPrepare event for hidden class\n");
380
failed = true;
381
}
382
return failed;
383
}
384
385
} // extern "C"
386
387