Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/Heap/libIterateHeapWithEscapeAnalysisEnabled.cpp
41153 views
1
/*
2
* Copyright (c) 2020 SAP SE. 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
#include "jni.h"
28
29
extern "C" {
30
31
#define FAILED -1
32
#define OK 0
33
34
static jvmtiEnv *jvmti;
35
36
static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
37
38
static void ShowErrorMessage(jvmtiEnv *jvmti, jvmtiError errCode, const char *message) {
39
char *errMsg;
40
jvmtiError result;
41
42
result = jvmti->GetErrorName(errCode, &errMsg);
43
if (result == JVMTI_ERROR_NONE) {
44
fprintf(stderr, "%s: %s (%d)\n", message, errMsg, errCode);
45
jvmti->Deallocate((unsigned char *)errMsg);
46
} else {
47
fprintf(stderr, "%s (%d)\n", message, errCode);
48
}
49
}
50
51
JNIEXPORT jint JNICALL
52
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
53
return Agent_Initialize(jvm, options, reserved);
54
}
55
56
JNIEXPORT jint JNICALL
57
Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
58
return Agent_Initialize(jvm, options, reserved);
59
}
60
61
JNIEXPORT jint JNICALL
62
JNI_OnLoad(JavaVM *jvm, void *reserved) {
63
jint res;
64
JNIEnv *env;
65
66
res = jvm->GetEnv((void **) &env, JNI_VERSION_9);
67
if (res != JNI_OK || env == NULL) {
68
fprintf(stderr, "Error: GetEnv call failed(%d)!\n", res);
69
return JNI_ERR;
70
}
71
72
return JNI_VERSION_9;
73
}
74
75
static jint
76
Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
77
jint res;
78
79
printf("Agent_OnLoad started\n");
80
81
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_9);
82
if (res != JNI_OK || jvmti == NULL) {
83
fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
84
return JNI_ERR;
85
}
86
87
printf("Agent_OnLoad finished\n");
88
return JNI_OK;
89
}
90
91
JNIEXPORT jint JNICALL
92
Java_IterateHeapWithEscapeAnalysisEnabled_acquireCanTagObjectsCapability(JNIEnv *env, jclass cls) {
93
jvmtiError err;
94
jvmtiCapabilities caps;
95
96
memset(&caps, 0, sizeof(caps));
97
98
caps.can_tag_objects = 1;
99
100
err = jvmti->AddCapabilities(&caps);
101
if (err != JVMTI_ERROR_NONE) {
102
ShowErrorMessage(jvmti, err,
103
"acquireCanTagObjectsCapability: error in JVMTI AddCapabilities");
104
return JNI_ERR;
105
}
106
107
err = jvmti->GetCapabilities(&caps);
108
if (err != JVMTI_ERROR_NONE) {
109
ShowErrorMessage(jvmti, err,
110
"acquireCanTagObjectsCapability: error in JVMTI GetCapabilities");
111
return JNI_ERR;
112
}
113
114
if (!caps.can_tag_objects) {
115
fprintf(stderr, "Warning: didn't get the capability can_tag_objects\n");
116
return JNI_ERR;
117
}
118
119
return JNI_OK;
120
}
121
122
static jobject method_IterateOverReachableObjects;
123
static jobject method_IterateOverHeap;
124
static jobject method_IterateOverInstancesOfClass;
125
static jobject method_FollowReferences;
126
static jobject method_IterateThroughHeap;
127
128
JNIEXPORT jint JNICALL
129
Java_IterateHeapWithEscapeAnalysisEnabled_registerMethod(JNIEnv *env, jclass cls, jobject method, jstring name) {
130
const char *name_chars = env->GetStringUTFChars(name, 0);
131
int rc = FAILED;
132
if (rc != OK && strcmp(name_chars, "IterateOverReachableObjects") == 0) {
133
method_IterateOverReachableObjects = env->NewGlobalRef(method);
134
rc = OK;
135
}
136
if (rc != OK && strcmp(name_chars, "IterateOverHeap") == 0) {
137
method_IterateOverHeap = env->NewGlobalRef(method);
138
rc = OK;
139
}
140
if (rc != OK && strcmp(name_chars, "IterateOverInstancesOfClass") == 0) {
141
method_IterateOverInstancesOfClass = env->NewGlobalRef(method);
142
rc = OK;
143
}
144
if (rc != OK && strcmp(name_chars, "IterateThroughHeap") == 0) {
145
method_IterateThroughHeap = env->NewGlobalRef(method);
146
rc = OK;
147
}
148
if (rc != OK && strcmp(name_chars, "FollowReferences") == 0) {
149
method_FollowReferences = env->NewGlobalRef(method);
150
rc = OK;
151
}
152
env->ReleaseStringUTFChars(name, name_chars);
153
return rc;
154
}
155
156
JNIEXPORT void JNICALL
157
Java_IterateHeapWithEscapeAnalysisEnabled_agentTearDown(JNIEnv *env, jclass cls) {
158
env->DeleteGlobalRef(method_IterateOverReachableObjects);
159
env->DeleteGlobalRef(method_IterateOverHeap);
160
env->DeleteGlobalRef(method_IterateOverInstancesOfClass);
161
env->DeleteGlobalRef(method_FollowReferences);
162
env->DeleteGlobalRef(method_IterateThroughHeap);
163
}
164
165
JNIEXPORT jint JNICALL
166
Java_IterateHeapWithEscapeAnalysisEnabled_jvmtiTagClass(JNIEnv *env, jclass cls, jclass clsToTag, jlong tag) {
167
jvmtiError err;
168
err = jvmti->SetTag(clsToTag, tag);
169
if (err != JVMTI_ERROR_NONE) {
170
ShowErrorMessage(jvmti, err,
171
"jvmtiTagClass: error in JVMTI SetTag");
172
return FAILED;
173
}
174
return OK;
175
}
176
177
typedef struct Tag_And_Counter {
178
jlong instance_counter;
179
jlong class_tag;
180
jlong instance_tag;
181
} Tag_And_Counter;
182
183
static jvmtiIterationControl JNICALL
184
__stackReferenceCallback(jvmtiHeapRootKind root_kind,
185
jlong class_tag,
186
jlong size,
187
jlong* tag_ptr,
188
jlong thread_tag,
189
jint depth,
190
jmethodID method,
191
jint slot,
192
void* d) {
193
Tag_And_Counter* data = (Tag_And_Counter*) d;
194
if (class_tag == data->class_tag && *tag_ptr == 0) {
195
data->instance_counter++;
196
*tag_ptr = data->instance_tag;
197
}
198
return JVMTI_ITERATION_CONTINUE;
199
}
200
201
static jvmtiIterationControl JNICALL
202
__jvmtiHeapObjectCallback(jlong class_tag, jlong size, jlong* tag_ptr, void* d) {
203
Tag_And_Counter* data = (Tag_And_Counter*) d;
204
if (class_tag == data->class_tag && *tag_ptr == 0) {
205
data->instance_counter++;
206
*tag_ptr = data->instance_tag;
207
}
208
return JVMTI_ITERATION_CONTINUE;
209
}
210
211
static jint JNICALL
212
__jvmtiHeapReferenceCallback(jvmtiHeapReferenceKind reference_kind,
213
const jvmtiHeapReferenceInfo* reference_info,
214
jlong class_tag,
215
jlong referrer_class_tag,
216
jlong size,
217
jlong* tag_ptr,
218
jlong* referrer_tag_ptr,
219
jint length,
220
void* d) {
221
Tag_And_Counter* data = (Tag_And_Counter*) d;
222
if (class_tag == data->class_tag && *tag_ptr == 0) {
223
data->instance_counter++;
224
*tag_ptr = data->instance_tag;
225
}
226
return JVMTI_VISIT_OBJECTS;
227
}
228
229
static jint JNICALL
230
__jvmtiHeapIterationCallback(jlong class_tag,
231
jlong size,
232
jlong* tag_ptr,
233
jint length,
234
void* d) {
235
Tag_And_Counter* data = (Tag_And_Counter*) d;
236
if (class_tag == data->class_tag && *tag_ptr == 0) {
237
data->instance_counter++;
238
*tag_ptr = data->instance_tag;
239
}
240
return JVMTI_VISIT_OBJECTS;
241
}
242
243
244
JNIEXPORT jlong JNICALL
245
Java_IterateHeapWithEscapeAnalysisEnabled_countAndTagInstancesOfClass(JNIEnv *env,
246
jclass cls,
247
jclass tagged_class,
248
jlong cls_tag,
249
jlong instance_tag,
250
jobject method) {
251
jvmtiError err;
252
jvmtiHeapCallbacks callbacks = {};
253
Tag_And_Counter data = {0, cls_tag, instance_tag};
254
jboolean method_found = JNI_FALSE;
255
256
jint idx = 0;
257
258
if (env->IsSameObject(method, method_IterateOverReachableObjects)) {
259
method_found = JNI_TRUE;
260
err = jvmti->IterateOverReachableObjects(NULL /*jvmtiHeapRootCallback*/,
261
__stackReferenceCallback,
262
NULL /* jvmtiObjectReferenceCallback */,
263
&data);
264
if (err != JVMTI_ERROR_NONE) {
265
ShowErrorMessage(jvmti, err,
266
"countAndTagInstancesOfClass: error in JVMTI IterateOverReachableObjects");
267
return FAILED;
268
}
269
}
270
if (env->IsSameObject(method, method_IterateOverHeap)) {
271
method_found = JNI_TRUE;
272
err = jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER,
273
__jvmtiHeapObjectCallback,
274
&data);
275
if (err != JVMTI_ERROR_NONE) {
276
ShowErrorMessage(jvmti, err,
277
"countAndTagInstancesOfClass: error in JVMTI IterateOverHeap");
278
return FAILED;
279
}
280
}
281
if (env->IsSameObject(method, method_IterateOverInstancesOfClass)) {
282
method_found = JNI_TRUE;
283
err = jvmti->IterateOverInstancesOfClass(tagged_class,
284
JVMTI_HEAP_OBJECT_EITHER,
285
__jvmtiHeapObjectCallback,
286
&data);
287
if (err != JVMTI_ERROR_NONE) {
288
ShowErrorMessage(jvmti, err,
289
"countAndTagInstancesOfClass: error in JVMTI IterateOverHeap");
290
return FAILED;
291
}
292
}
293
if (env->IsSameObject(method, method_FollowReferences)) {
294
method_found = JNI_TRUE;
295
callbacks.heap_reference_callback = __jvmtiHeapReferenceCallback;
296
err = jvmti->FollowReferences(0 /* filter nothing */,
297
NULL /* no class filter */,
298
NULL /* no initial object, follow roots */,
299
&callbacks,
300
&data);
301
if (err != JVMTI_ERROR_NONE) {
302
ShowErrorMessage(jvmti, err,
303
"countAndTagInstancesOfClass: error in JVMTI FollowReferences");
304
return FAILED;
305
}
306
}
307
if (env->IsSameObject(method, method_IterateThroughHeap)) {
308
method_found = JNI_TRUE;
309
callbacks.heap_iteration_callback = __jvmtiHeapIterationCallback;
310
err = jvmti->IterateThroughHeap(0 /* filter nothing */,
311
NULL /* no class filter */,
312
&callbacks,
313
&data);
314
if (err != JVMTI_ERROR_NONE) {
315
ShowErrorMessage(jvmti, err,
316
"countAndTagInstancesOfClass: error in JVMTI IterateThroughHeap");
317
return FAILED;
318
}
319
}
320
321
if (!method_found) {
322
fprintf(stderr, "countAndTagInstancesOfClass: unknown method\n");
323
return FAILED;
324
}
325
326
return data.instance_counter;
327
}
328
329
JNIEXPORT jlong JNICALL
330
Java_IterateHeapWithEscapeAnalysisEnabled_getObjectsWithTag(JNIEnv *env,
331
jclass cls,
332
jlong tag,
333
jobjectArray res_instances) {
334
jvmtiError err;
335
const jlong tags[1] = {tag};
336
jint res_count = -1;
337
jobject* res_instances_raw;
338
jlong* res_tags;
339
jint res_instances_length;
340
jint idx;
341
342
err = jvmti->GetObjectsWithTags(1,
343
tags,
344
&res_count,
345
&res_instances_raw,
346
&res_tags);
347
if (err != JVMTI_ERROR_NONE) {
348
ShowErrorMessage(jvmti, err,
349
"getObjectsWithTags: error in JVMTI GetObjectsWithTags");
350
return FAILED;
351
}
352
353
res_instances_length = env->GetArrayLength(res_instances);
354
if (res_count != res_instances_length) {
355
fprintf(stderr, "getObjectsWithTags: result array lenght (%d) does not match instance count returned by GetObjectsWithTags (%d) \n",
356
res_instances_length, res_count);
357
return FAILED;
358
}
359
360
for (idx = 0; idx < res_count; idx++) {
361
env->SetObjectArrayElement(res_instances, idx, res_instances_raw[idx]);
362
}
363
364
jvmti->Deallocate((unsigned char *)res_instances_raw);
365
jvmti->Deallocate((unsigned char *)res_tags);
366
367
return OK;
368
}
369
370
}
371
372