Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/heapViewer/heapViewer.c
38827 views
1
/*
2
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* - Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
*
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* - Neither the name of Oracle nor the names of its
16
* contributors may be used to endorse or promote products derived
17
* from this software without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
/*
33
* This source code is provided to illustrate the usage of a given feature
34
* or technique and has been deliberately simplified. Additional steps
35
* required for a production-quality application, such as security checks,
36
* input validation and proper error handling, might not be present in
37
* this sample code.
38
*/
39
40
41
#include <stdio.h>
42
#include <stddef.h>
43
#include <stdlib.h>
44
#include <string.h>
45
46
#include "jni.h"
47
#include "jvmti.h"
48
49
#include "agent_util.h"
50
51
/* Global static data */
52
typedef struct {
53
jboolean vmDeathCalled;
54
jboolean dumpInProgress;
55
jrawMonitorID lock;
56
} GlobalData;
57
static GlobalData globalData, *gdata = &globalData;
58
59
/* Typedef to hold class details */
60
typedef struct {
61
char *signature;
62
int count;
63
int space;
64
} ClassDetails;
65
66
/* Enter agent monitor protected section */
67
static void
68
enterAgentMonitor(jvmtiEnv *jvmti)
69
{
70
jvmtiError err;
71
72
err = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
73
check_jvmti_error(jvmti, err, "raw monitor enter");
74
}
75
76
/* Exit agent monitor protected section */
77
static void
78
exitAgentMonitor(jvmtiEnv *jvmti)
79
{
80
jvmtiError err;
81
82
err = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
83
check_jvmti_error(jvmti, err, "raw monitor exit");
84
}
85
86
/* Heap object callback */
87
static jint JNICALL
88
cbHeapObject(jlong class_tag, jlong size, jlong* tag_ptr, jint length,
89
void* user_data)
90
{
91
if ( class_tag != (jlong)0 ) {
92
ClassDetails *d;
93
94
d = (ClassDetails*)(void*)(ptrdiff_t)class_tag;
95
(*((jint*)(user_data)))++;
96
d->count++;
97
d->space += (int)size;
98
}
99
return JVMTI_VISIT_OBJECTS;
100
}
101
102
/* Compare two ClassDetails */
103
static int
104
compareDetails(const void *p1, const void *p2)
105
{
106
return ((ClassDetails*)p2)->space - ((ClassDetails*)p1)->space;
107
}
108
109
/* Callback for JVMTI_EVENT_DATA_DUMP_REQUEST (Ctrl-\ or at exit) */
110
static void JNICALL
111
dataDumpRequest(jvmtiEnv *jvmti)
112
{
113
enterAgentMonitor(jvmti); {
114
if ( !gdata->vmDeathCalled && !gdata->dumpInProgress ) {
115
jvmtiHeapCallbacks heapCallbacks;
116
ClassDetails *details;
117
jvmtiError err;
118
jclass *classes;
119
jint totalCount;
120
jint count;
121
jint i;
122
123
gdata->dumpInProgress = JNI_TRUE;
124
125
/* Get all the loaded classes */
126
err = (*jvmti)->GetLoadedClasses(jvmti, &count, &classes);
127
check_jvmti_error(jvmti, err, "get loaded classes");
128
129
/* Setup an area to hold details about these classes */
130
details = (ClassDetails*)calloc(sizeof(ClassDetails), count);
131
if ( details == NULL ) {
132
fatal_error("ERROR: Ran out of malloc space\n");
133
}
134
for ( i = 0 ; i < count ; i++ ) {
135
char *sig;
136
137
/* Get and save the class signature */
138
err = (*jvmti)->GetClassSignature(jvmti, classes[i], &sig, NULL);
139
check_jvmti_error(jvmti, err, "get class signature");
140
if ( sig == NULL ) {
141
fatal_error("ERROR: No class signature found\n");
142
}
143
details[i].signature = strdup(sig);
144
deallocate(jvmti, sig);
145
146
/* Tag this jclass */
147
err = (*jvmti)->SetTag(jvmti, classes[i],
148
(jlong)(ptrdiff_t)(void*)(&details[i]));
149
check_jvmti_error(jvmti, err, "set object tag");
150
}
151
152
/* Iterate through the heap and count up uses of jclass */
153
(void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
154
heapCallbacks.heap_iteration_callback = &cbHeapObject;
155
totalCount = 0;
156
err = (*jvmti)->IterateThroughHeap(jvmti,
157
JVMTI_HEAP_FILTER_CLASS_UNTAGGED, NULL,
158
&heapCallbacks, (const void *)&totalCount);
159
check_jvmti_error(jvmti, err, "iterate through heap");
160
161
/* Remove tags */
162
for ( i = 0 ; i < count ; i++ ) {
163
/* Un-Tag this jclass */
164
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)0);
165
check_jvmti_error(jvmti, err, "set object tag");
166
}
167
168
/* Sort details by space used */
169
qsort(details, count, sizeof(ClassDetails), &compareDetails);
170
171
/* Print out sorted table */
172
stdout_message("Heap View, Total of %d objects found.\n\n",
173
totalCount);
174
175
stdout_message("Space Count Class Signature\n");
176
stdout_message("---------- ---------- ----------------------\n");
177
178
for ( i = 0 ; i < count ; i++ ) {
179
if ( details[i].space == 0 || i > 20 ) {
180
break;
181
}
182
stdout_message("%10d %10d %s\n",
183
details[i].space, details[i].count, details[i].signature);
184
}
185
stdout_message("---------- ---------- ----------------------\n\n");
186
187
/* Free up all allocated space */
188
deallocate(jvmti, classes);
189
for ( i = 0 ; i < count ; i++ ) {
190
if ( details[i].signature != NULL ) {
191
free(details[i].signature);
192
}
193
}
194
free(details);
195
196
gdata->dumpInProgress = JNI_FALSE;
197
}
198
} exitAgentMonitor(jvmti);
199
}
200
201
/* Callback for JVMTI_EVENT_VM_INIT */
202
static void JNICALL
203
vmInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
204
{
205
enterAgentMonitor(jvmti); {
206
jvmtiError err;
207
208
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
209
JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
210
check_jvmti_error(jvmti, err, "set event notification");
211
} exitAgentMonitor(jvmti);
212
}
213
214
/* Callback for JVMTI_EVENT_VM_DEATH */
215
static void JNICALL
216
vmDeath(jvmtiEnv *jvmti, JNIEnv *env)
217
{
218
jvmtiError err;
219
220
/* Make sure everything has been garbage collected */
221
err = (*jvmti)->ForceGarbageCollection(jvmti);
222
check_jvmti_error(jvmti, err, "force garbage collection");
223
224
/* Disable events and dump the heap information */
225
enterAgentMonitor(jvmti); {
226
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE,
227
JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
228
check_jvmti_error(jvmti, err, "set event notification");
229
230
dataDumpRequest(jvmti);
231
232
gdata->vmDeathCalled = JNI_TRUE;
233
} exitAgentMonitor(jvmti);
234
}
235
236
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
237
JNIEXPORT jint JNICALL
238
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
239
{
240
jint rc;
241
jvmtiError err;
242
jvmtiCapabilities capabilities;
243
jvmtiEventCallbacks callbacks;
244
jvmtiEnv *jvmti;
245
246
/* Get JVMTI environment */
247
jvmti = NULL;
248
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
249
if (rc != JNI_OK) {
250
fatal_error("ERROR: Unable to create jvmtiEnv, error=%d\n", rc);
251
return -1;
252
}
253
if ( jvmti == NULL ) {
254
fatal_error("ERROR: No jvmtiEnv* returned from GetEnv\n");
255
}
256
257
/* Get/Add JVMTI capabilities */
258
(void)memset(&capabilities, 0, sizeof(capabilities));
259
capabilities.can_tag_objects = 1;
260
capabilities.can_generate_garbage_collection_events = 1;
261
err = (*jvmti)->AddCapabilities(jvmti, &capabilities);
262
check_jvmti_error(jvmti, err, "add capabilities");
263
264
/* Create the raw monitor */
265
err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &(gdata->lock));
266
check_jvmti_error(jvmti, err, "create raw monitor");
267
268
/* Set callbacks and enable event notifications */
269
memset(&callbacks, 0, sizeof(callbacks));
270
callbacks.VMInit = &vmInit;
271
callbacks.VMDeath = &vmDeath;
272
callbacks.DataDumpRequest = &dataDumpRequest;
273
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
274
check_jvmti_error(jvmti, err, "set event callbacks");
275
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
276
JVMTI_EVENT_VM_INIT, NULL);
277
check_jvmti_error(jvmti, err, "set event notifications");
278
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
279
JVMTI_EVENT_VM_DEATH, NULL);
280
check_jvmti_error(jvmti, err, "set event notifications");
281
return 0;
282
}
283
284
/* Agent_OnUnload() is called last */
285
JNIEXPORT void JNICALL
286
Agent_OnUnload(JavaVM *vm)
287
{
288
}
289
290