Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c
41159 views
1
/*
2
* Copyright (c) 2016, 2017, 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 <stdio.h>
25
#include <string.h>
26
#include "jvmti.h"
27
28
#ifdef __cplusplus
29
extern "C" {
30
#endif
31
32
#ifndef JNI_ENV_ARG
33
34
#ifdef __cplusplus
35
#define JNI_ENV_ARG(x, y) y
36
#define JNI_ENV_PTR(x) x
37
#else
38
#define JNI_ENV_ARG(x,y) x, y
39
#define JNI_ENV_PTR(x) (*x)
40
#endif
41
42
#endif
43
44
#define TranslateError(err) "JVMTI error"
45
46
#define PASSED 0
47
#define FAILED 2
48
49
static const char *EXPECTED_NAME = "java/util/Collections";
50
static const char *EXC_CNAME = "java/lang/Exception";
51
52
static jvmtiEnv *jvmti = NULL;
53
static jint result = PASSED;
54
static jboolean printdump = JNI_FALSE;
55
56
static jboolean with_early_vm_start_capability = JNI_FALSE;
57
static jboolean with_early_class_hook_capability = JNI_FALSE;
58
59
static jboolean found_class_in_vm_start = JNI_FALSE;
60
static jboolean found_class_in_primordial = JNI_FALSE;
61
static jboolean found_class_in_cflh_events = JNI_FALSE;
62
63
static int cflh_events_primordial_count = 0;
64
static int cflh_events_vm_start_count = 0;
65
66
static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
67
68
JNIEXPORT
69
jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
70
return Agent_Initialize(jvm, options, reserved);
71
}
72
73
JNIEXPORT
74
jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
75
return Agent_Initialize(jvm, options, reserved);
76
}
77
78
JNIEXPORT
79
jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
80
return JNI_VERSION_9;
81
}
82
83
static
84
jint throw_exc(JNIEnv *env, char *msg) {
85
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
86
87
if (exc_class == NULL) {
88
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
89
return -1;
90
}
91
return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
92
}
93
94
static void JNICALL
95
Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
96
jclass class_being_redefined,
97
jobject loader, const char* name, jobject protection_domain,
98
jint class_data_len, const unsigned char* class_data,
99
jint *new_class_data_len, unsigned char** new_class_data) {
100
jvmtiPhase phase;
101
jvmtiError err;
102
103
err = (*jvmti)->GetPhase(jvmti_env, &phase);
104
if (err != JVMTI_ERROR_NONE) {
105
printf("ClassFileLoadHook event: GetPhase error: %s (%d)\n", TranslateError(err), err);
106
result = FAILED;
107
return;
108
}
109
110
if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {
111
if (phase == JVMTI_PHASE_START) {
112
cflh_events_vm_start_count++;
113
if(strcmp(name, EXPECTED_NAME) == 0) {
114
found_class_in_vm_start = JNI_TRUE;
115
}
116
} else {
117
cflh_events_primordial_count++;
118
if(strcmp(name, EXPECTED_NAME) == 0) {
119
found_class_in_primordial = JNI_TRUE;
120
}
121
}
122
}
123
124
if(strcmp(name, EXPECTED_NAME) == 0) {
125
found_class_in_cflh_events = JNI_TRUE;
126
}
127
128
if (printdump == JNI_TRUE) {
129
printf(">>> ClassFileLoadHook event: phase(%d), class name %s\n", phase, name);
130
}
131
}
132
133
static
134
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
135
jint res, size;
136
jvmtiCapabilities caps;
137
jvmtiEventCallbacks callbacks;
138
jvmtiError err;
139
140
printf("agent options: %s\n", options);
141
if (options != NULL) {
142
if (strstr(options, "with_early_vmstart") != NULL) {
143
with_early_vm_start_capability = JNI_TRUE;
144
}
145
if (strstr(options, "with_early_class_hook") != NULL) {
146
with_early_class_hook_capability = JNI_TRUE;
147
}
148
if (strstr(options, "printdump") != NULL) {
149
printdump = JNI_TRUE;
150
}
151
}
152
153
res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
154
JVMTI_VERSION_9);
155
if (res != JNI_OK || jvmti == NULL) {
156
printf(" Error: wrong result of a valid call to GetEnv!\n");
157
return JNI_ERR;
158
}
159
160
printf("Enabling following capabilities: can_generate_all_class_hook_events");
161
memset(&caps, 0, sizeof(caps));
162
caps.can_generate_all_class_hook_events = 1;
163
if (with_early_vm_start_capability == JNI_TRUE) {
164
printf(", can_generate_early_vmstart");
165
caps.can_generate_early_vmstart = 1;
166
}
167
if (with_early_class_hook_capability == JNI_TRUE) {
168
printf(", can_generate_early_class_hook_events");
169
caps.can_generate_early_class_hook_events = 1;
170
}
171
printf("\n");
172
173
err = (*jvmti)->AddCapabilities(jvmti, &caps);
174
if (err != JVMTI_ERROR_NONE) {
175
printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
176
return JNI_ERR;
177
}
178
179
size = (jint)sizeof(callbacks);
180
181
memset(&callbacks, 0, sizeof(callbacks));
182
callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
183
184
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
185
if (err != JVMTI_ERROR_NONE) {
186
printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
187
return JNI_ERR;
188
}
189
190
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
191
if (err != JVMTI_ERROR_NONE) {
192
printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
193
return JNI_ERR;
194
}
195
196
return JNI_OK;
197
}
198
199
JNIEXPORT jint JNICALL
200
Java_MAAClassFileLoadHook_check(JNIEnv *env, jclass cls) {
201
jobject loader = NULL;
202
203
if (jvmti == NULL) {
204
throw_exc(env, "JVMTI client was not properly loaded!\n");
205
return FAILED;
206
}
207
208
/*
209
* Expecting ClassFileLoadHook events in the VM Start phase if early_vm_start is enabled.
210
*/
211
if (with_early_vm_start_capability == JNI_TRUE && cflh_events_vm_start_count == 0) {
212
throw_exc(env, "Didn't get ClassFileLoadHook events in start phase!\n");
213
return FAILED;
214
}
215
216
if (with_early_class_hook_capability == JNI_TRUE) {
217
/*
218
* Expecting that we get ClassFileLoadHook events in the Primordial phase
219
* when can_generate_all_class_hook_events and can_generate_early_class_hook_events
220
* capabilities are enabled.
221
*/
222
if (cflh_events_primordial_count == 0) {
223
throw_exc(env, "Didn't get ClassFileLoadHook events in primordial phase!\n");
224
return FAILED;
225
}
226
} else {
227
/*
228
* Expecting that we don't get ClassFileLoadHook events in the Primordial phase
229
* when can_generate_early_class_hook_events capability is disabled.
230
*/
231
if (cflh_events_primordial_count != 0) {
232
throw_exc(env, "Get ClassFileLoadHook events in primordial phase!\n");
233
return FAILED;
234
}
235
}
236
237
238
if (with_early_vm_start_capability == JNI_TRUE) {
239
/*
240
* Expecting that "java/util/Collections" class from java.base module is present in the
241
* ClassFileLoadHook events during VM Start phase when can_generate_early_vmstart
242
* capability is enabled.
243
*/
244
printf("Expecting to find '%s' class in ClassFileLoadHook events during VM early start phase.\n", EXPECTED_NAME);
245
if (found_class_in_vm_start == JNI_FALSE) {
246
throw_exc(env, "Unable to find expected class in ClassLoad events during VM early start phase!\n");
247
return FAILED;
248
}
249
} else if (with_early_class_hook_capability == JNI_TRUE) {
250
/*
251
* Expecting that "java/util/Collections" class from java.base module is present in the
252
* ClassFileLoadHook events during Primordial phase when can_generate_all_class_hook_events
253
* and can_generate_early_class_hook_events capabilities are enabled and can_generate_early_vmstart
254
* capability is disabled.
255
*/
256
printf("Expecting to find '%s' class in ClassFileLoadHook events during VM primordial phase.\n", EXPECTED_NAME);
257
if (found_class_in_primordial == JNI_FALSE) {
258
throw_exc(env, "Unable to find expected class in ClassFileLoadHook events during primordial phase!\n");
259
return FAILED;
260
}
261
} else {
262
/*
263
* Expecting that "java/util/Collections" class from java.base module is not present in the
264
* ClassFileLoadHook events when can_generate_all_class_hook_events, can_generate_early_class_hook_events
265
* and can_generate_early_vmstart capabilities are disabled.
266
*/
267
printf("Expecting that '%s' class is absent in ClassLoadHook events.\n", EXPECTED_NAME);
268
if (found_class_in_cflh_events == JNI_TRUE) {
269
throw_exc(env, "Class is found in ClassFileLoadHook events!\n");
270
return FAILED;
271
}
272
}
273
274
return result;
275
}
276
277
#ifdef __cplusplus
278
}
279
#endif
280
281