Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/mgmtinit.c
6000 views
1
/*******************************************************************************
2
* Copyright (c) 1998, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "jni.h"
24
#include "j9.h"
25
#include "mmhook.h"
26
#include "mmomrhook.h"
27
#include "jithook.h"
28
#include "j9consts.h"
29
#include "omrgcconsts.h"
30
#include "j9modron.h"
31
#include "jcl_internal.h"
32
33
#include "mgmtinit.h"
34
35
/* required for memset */
36
#include <string.h>
37
38
#include "ut_j9jcl.h"
39
40
typedef enum {
41
CLASS_MEMORY=0,
42
MISC_MEMORY,
43
JIT_CODECACHE,
44
JIT_DATACACHE
45
} nonHeapMemoryPoolIndex;
46
47
static void managementClassLoadCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
48
#if (defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING))
49
static void managementClassUnloadCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
50
#endif
51
static void managementCompilingStartTime(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
52
static void managementCompilingEndTime(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
53
static void managementThreadStartCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
54
static void managementThreadEndCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
55
56
static VMINLINE void managementGC(OMR_VMThread *omrVMThread, void *userData, BOOLEAN isEnd);
57
static void managementGlobalGCStart(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
58
static void managementGlobalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
59
static void managementLocalGCStart(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
60
static void managementLocalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
61
62
static void managementCompactEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
63
static void gcStartEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *frees, UDATA collectorID);
64
static void gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *frees, UDATA *maxs, UDATA collectorID, OMR_VMThread *omrVMThread);
65
static jint initMemoryManagement(J9JavaVM *vm);
66
static U_32 getNumberSupported(U_32 supportedIDs);
67
static UDATA getArrayIndexFromManagerID(J9JavaLangManagementData *mgmt, UDATA id);
68
static void getSegmentSizes(J9JavaVM *javaVM, J9MemorySegmentList *segList, U_64 *storedSize, U_64 *storedUsed, U_64 *storedPeakSize, U_64 *storedPeakUsed, BOOLEAN isCodeCacheSegment);
69
static void updateNonHeapMemoryPoolSizes(J9JavaVM *vm, J9JavaLangManagementData *mgmt, BOOLEAN isGCEnd);
70
71
/* initialize java.lang.management data structures and hooks */
72
jint
73
managementInit(J9JavaVM *vm)
74
{
75
J9HookInterface **vmHooks = NULL;
76
J9HookInterface **omrGCHooks = NULL;
77
J9VMThread *walkThread = NULL;
78
J9JavaLangManagementData *mgmt = NULL;
79
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
80
#if defined (J9VM_INTERP_NATIVE_SUPPORT)
81
J9HookInterface **jitHooks = NULL;
82
#endif
83
omrthread_t self = omrthread_self();
84
PORT_ACCESS_FROM_JAVAVM(vm);
85
86
/* allocate management data struct */
87
vm->managementData = j9mem_allocate_memory(sizeof(J9JavaLangManagementData), J9MEM_CATEGORY_VM_JCL);
88
mgmt = vm->managementData;
89
if (NULL == mgmt) {
90
return JNI_ERR;
91
}
92
memset(mgmt, 0, sizeof(J9JavaLangManagementData));
93
94
/* init monitor used to protect access to the U64 fields in the management data */
95
if (omrthread_rwmutex_init(&mgmt->managementDataLock, 0, "management fields lock")) {
96
return JNI_ERR;
97
}
98
99
if (JNI_ERR == initMemoryManagement(vm)) {
100
return JNI_ERR;
101
}
102
103
/* init monitor used to wake up the heap threshold notification thread */
104
if (omrthread_monitor_init(&mgmt->notificationMonitor, 0)) {
105
return JNI_ERR;
106
}
107
108
mgmt->threadCpuTimeEnabledFlag = 1;
109
if (0 <= omrthread_get_cpu_time(self)) {
110
mgmt->isThreadCpuTimeSupported = 1;
111
} else {
112
mgmt->isThreadCpuTimeSupported = 0;
113
}
114
if (0 <= omrthread_get_self_cpu_time(self)) {
115
mgmt->isCurrentThreadCpuTimeSupported = 1;
116
} else {
117
mgmt->isCurrentThreadCpuTimeSupported = 0;
118
}
119
/* isThreadCpuTimeSupported and isCurrentThreadCpuTimeSupported are read-only after this point */
120
121
mgmt->vmStartTime = j9time_current_time_millis();
122
123
/* vm->memoryManagerFunctions will be NULL if we failed to load the gc dll */
124
if (NULL == mmFuncs) {
125
return JNI_ERR;
126
}
127
128
mgmt->initialHeapSize = mmFuncs->j9gc_get_initial_heap_size(vm);
129
mgmt->maximumHeapSize = mmFuncs->j9gc_get_maximum_heap_size(vm);
130
131
/* hook class load and unload */
132
vmHooks = vm->internalVMFunctions->getVMHookInterface(vm);
133
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_INTERNAL_CLASS_LOAD, managementClassLoadCounter, OMR_GET_CALLSITE(), mgmt)) {
134
return JNI_ERR;
135
}
136
137
#ifdef J9VM_GC_DYNAMIC_CLASS_UNLOADING
138
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, managementClassUnloadCounter, OMR_GET_CALLSITE(), mgmt)) {
139
return JNI_ERR;
140
}
141
#endif
142
143
/* hook GC start/end events */
144
omrGCHooks = mmFuncs->j9gc_get_omr_hook_interface(vm->omrVM);
145
146
if ((*omrGCHooks)->J9HookRegisterWithCallSite(omrGCHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, managementGlobalGCStart, OMR_GET_CALLSITE(), vm)) {
147
return JNI_ERR;
148
}
149
if ((*omrGCHooks)->J9HookRegisterWithCallSite(omrGCHooks, J9HOOK_MM_OMR_LOCAL_GC_START, managementLocalGCStart, OMR_GET_CALLSITE(), vm)) {
150
return JNI_ERR;
151
}
152
if ((*omrGCHooks)->J9HookRegisterWithCallSite(omrGCHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, managementGlobalGCEnd, OMR_GET_CALLSITE(), vm)) {
153
return JNI_ERR;
154
}
155
if ((*omrGCHooks)->J9HookRegisterWithCallSite(omrGCHooks, J9HOOK_MM_OMR_LOCAL_GC_END, managementLocalGCEnd, OMR_GET_CALLSITE(), vm)) {
156
return JNI_ERR;
157
}
158
if ((*omrGCHooks)->J9HookRegisterWithCallSite(omrGCHooks, J9HOOK_MM_OMR_COMPACT_END, managementCompactEnd, OMR_GET_CALLSITE(), vm)) {
159
return JNI_ERR;
160
}
161
162
/* lock the thread list */
163
omrthread_monitor_enter(vm->vmThreadListMutex);
164
165
/* count existing threads */
166
walkThread = vm->mainThread;
167
do {
168
mgmt->liveJavaThreads++;
169
if (walkThread->privateFlags & J9_PRIVATE_FLAGS_DAEMON_THREAD) {
170
mgmt->liveJavaDaemonThreads++;
171
}
172
} while((walkThread = walkThread->linkNext) != vm->mainThread);
173
174
mgmt->totalJavaThreadsStarted = mgmt->liveJavaThreads;
175
mgmt->peakLiveJavaThreads = mgmt->liveJavaThreads;
176
177
/* hook thread create and destroy while holding the thread list mutex, so our initial counts stay correct */
178
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CREATED, managementThreadStartCounter, OMR_GET_CALLSITE(), mgmt)) {
179
omrthread_monitor_exit(vm->vmThreadListMutex);
180
return JNI_ERR;
181
}
182
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_DESTROY, managementThreadEndCounter, OMR_GET_CALLSITE(), mgmt)) {
183
omrthread_monitor_exit(vm->vmThreadListMutex);
184
return JNI_ERR;
185
}
186
187
omrthread_monitor_exit(vm->vmThreadListMutex);
188
189
#if defined (J9VM_INTERP_NATIVE_SUPPORT)
190
/* hook jit compile start/end events */
191
jitHooks = vm->internalVMFunctions->getJITHookInterface(vm);
192
if (jitHooks) {
193
if ((*jitHooks)->J9HookRegisterWithCallSite(jitHooks, J9HOOK_JIT_COMPILING_START, managementCompilingStartTime, OMR_GET_CALLSITE(), mgmt)) {
194
return JNI_ERR;
195
}
196
if ((*jitHooks)->J9HookRegisterWithCallSite(jitHooks, J9HOOK_JIT_COMPILING_END, managementCompilingEndTime, OMR_GET_CALLSITE(), mgmt)) {
197
return JNI_ERR;
198
}
199
}
200
#endif
201
202
/* Initialization for OperatingSystemNotificationThread (mgmtos.c)
203
* OperatingSystemNotificationThread must be a singleton class.
204
*/
205
if (J9THREAD_SUCCESS != omrthread_monitor_init(&mgmt->dlparNotificationMonitor, 0)) {
206
mgmt->dlparNotificationMonitor = NULL;
207
}
208
mgmt->dlparNotificationQueue = NULL;
209
mgmt->dlparNotificationsPending = 0;
210
mgmt->isCounterPathInitialized = 0;
211
return 0;
212
}
213
214
static void
215
managementClassLoadCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
216
{
217
J9JavaLangManagementData *mgmt = userData;
218
219
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
220
221
mgmt->totalClassLoads++;
222
223
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
224
}
225
226
227
#if (defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING))
228
229
static void
230
managementClassUnloadCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
231
{
232
J9VMClassesUnloadEvent *data = eventData;
233
J9JavaLangManagementData *mgmt = userData;
234
235
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
236
mgmt->totalClassUnloads += data->classUnloadCount;
237
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
238
}
239
#endif
240
241
242
static void
243
managementCompilingStartTime(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
244
{
245
J9CompilingStartEvent *event = eventData;
246
J9JavaVM *vm = event->currentThread->javaVM;
247
PORT_ACCESS_FROM_JAVAVM(vm);
248
J9JavaLangManagementData *mgmt = userData;
249
I_64 now;
250
251
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
252
253
now = j9time_nano_time();
254
if (0 < mgmt->threadsCompiling) {
255
mgmt->totalCompilationTime += checkedTimeInterval((U_64)now, (U_64)mgmt->lastCompilationStart) * mgmt->threadsCompiling;
256
}
257
258
mgmt->lastCompilationStart = now;
259
mgmt->threadsCompiling++;
260
261
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
262
}
263
static void
264
managementCompilingEndTime(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
265
{
266
J9CompilingEndEvent *event = eventData;
267
J9JavaVM* vm = event->currentThread->javaVM;
268
PORT_ACCESS_FROM_JAVAVM(vm);
269
J9JavaLangManagementData *mgmt = userData;
270
271
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
272
273
mgmt->totalCompilationTime += checkedTimeInterval((U_64)j9time_nano_time(), (U_64)mgmt->lastCompilationStart);
274
mgmt->threadsCompiling--;
275
276
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
277
}
278
/* tear down java.lang.management data structures and hooks */
279
void
280
managementTerminate(J9JavaVM *vm)
281
{
282
J9HookInterface **vmHooks = NULL;
283
J9HookInterface **omrGCHooks = NULL;
284
J9JavaLangManagementData *mgmt = vm->managementData;
285
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
286
#if defined (J9VM_INTERP_NATIVE_SUPPORT)
287
J9HookInterface **jitHooks;
288
#endif
289
PORT_ACCESS_FROM_JAVAVM(vm);
290
291
if (NULL == mgmt) {
292
/* managementInit was never called, we have nothing to clean up */
293
return;
294
}
295
296
/* unhook class load and unload */
297
vmHooks = vm->internalVMFunctions->getVMHookInterface(vm);
298
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_INTERNAL_CLASS_LOAD, managementClassLoadCounter, mgmt);
299
300
#ifdef J9VM_GC_DYNAMIC_CLASS_UNLOADING
301
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, managementClassUnloadCounter, mgmt);
302
#endif
303
304
305
/* vm->memoryManagerFunctions will be NULL if we failed to load the gc dll */
306
if (NULL != mmFuncs) {
307
/* unhook GC start/end */
308
omrGCHooks = mmFuncs->j9gc_get_omr_hook_interface(vm->omrVM);
309
310
(*omrGCHooks)->J9HookUnregister(omrGCHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, managementGlobalGCStart, vm);
311
(*omrGCHooks)->J9HookUnregister(omrGCHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, managementGlobalGCEnd, vm);
312
(*omrGCHooks)->J9HookUnregister(omrGCHooks, J9HOOK_MM_OMR_LOCAL_GC_START, managementLocalGCStart, vm);
313
(*omrGCHooks)->J9HookUnregister(omrGCHooks, J9HOOK_MM_OMR_LOCAL_GC_END, managementLocalGCEnd, vm);
314
(*omrGCHooks)->J9HookUnregister(omrGCHooks, J9HOOK_MM_OMR_COMPACT_END, managementCompactEnd, vm);
315
}
316
317
/* unhook thread start and end */
318
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_THREAD_CREATED, managementThreadStartCounter, mgmt);
319
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_THREAD_DESTROY, managementThreadEndCounter, mgmt);
320
321
#if defined (J9VM_INTERP_NATIVE_SUPPORT)
322
/* unhook jit compile start/end events */
323
jitHooks = vm->internalVMFunctions->getJITHookInterface(vm);
324
if (jitHooks) {
325
(*jitHooks)->J9HookUnregister(jitHooks, J9HOOK_JIT_COMPILING_START, managementCompilingStartTime, mgmt);
326
(*jitHooks)->J9HookUnregister(jitHooks, J9HOOK_JIT_COMPILING_END, managementCompilingEndTime, mgmt);
327
}
328
#endif
329
330
/* destroy monitor */
331
omrthread_rwmutex_destroy(mgmt->managementDataLock);
332
333
omrthread_monitor_destroy(mgmt->notificationMonitor);
334
335
/* Cleanup for OperatingSystemNotificationThread (mgmtos.c) */
336
if (NULL != mgmt->dlparNotificationMonitor) {
337
omrthread_monitor_destroy(mgmt->dlparNotificationMonitor);
338
}
339
340
/* deallocate management data struct */
341
j9mem_free_memory(mgmt->memoryPools);
342
j9mem_free_memory(mgmt->garbageCollectors);
343
j9mem_free_memory(mgmt->nonHeapMemoryPools);
344
j9mem_free_memory(vm->managementData);
345
}
346
347
static void
348
managementThreadStartCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
349
{
350
J9JavaLangManagementData *mgmt = userData;
351
J9VMThreadCreatedEvent *event = (J9VMThreadCreatedEvent *)eventData;
352
J9VMThread *vmThread = event->vmThread;
353
354
if (NULL != vmThread) {
355
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
356
357
mgmt->totalJavaThreadsStarted++;
358
mgmt->liveJavaThreads++;
359
if (mgmt->liveJavaThreads > mgmt->peakLiveJavaThreads) {
360
mgmt->peakLiveJavaThreads = mgmt->liveJavaThreads;
361
}
362
if (J9_PRIVATE_FLAGS_DAEMON_THREAD & vmThread->privateFlags) {
363
mgmt->liveJavaDaemonThreads++;
364
}
365
366
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
367
}
368
}
369
static void
370
managementThreadEndCounter(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
371
{
372
J9JavaLangManagementData *mgmt = userData;
373
J9VMThreadDestroyEvent *event = (J9VMThreadDestroyEvent *)eventData;
374
J9VMThread *vmThread = event->vmThread;
375
376
if (NULL != vmThread) {
377
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
378
379
mgmt->liveJavaThreads--;
380
if (J9_PRIVATE_FLAGS_DAEMON_THREAD & vmThread->privateFlags) {
381
mgmt->liveJavaDaemonThreads--;
382
}
383
384
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
385
}
386
}
387
388
static void
389
managementGC(OMR_VMThread *omrVMThread, void *userData, BOOLEAN isEnd)
390
{
391
J9JavaVM *vm = userData;
392
UDATA heapSize = 0;
393
UDATA heapFree = 0;
394
UDATA heapUsed = 0;
395
UDATA totals[J9VM_MAX_HEAP_MEMORYPOOL_COUNT];
396
UDATA frees[J9VM_MAX_HEAP_MEMORYPOOL_COUNT];
397
UDATA maxs[J9VM_MAX_HEAP_MEMORYPOOL_COUNT];
398
UDATA collectorID = 0;
399
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
400
U_32 supportedMemoryPoolIDs = 0;
401
U_32 id = 0;
402
U_32 mask = 0;
403
UDATA idx = 0;
404
UDATA count = 0;
405
406
collectorID = mmFuncs->j9gc_get_collector_id(omrVMThread);
407
408
if (0 == collectorID) {
409
/* only record data for "stop the world" collector */
410
return;
411
}
412
413
heapSize = mmFuncs->j9gc_heap_total_memory(vm);
414
heapFree = mmFuncs->j9gc_heap_free_memory(vm);
415
heapUsed = heapSize - heapFree;
416
417
mmFuncs->j9gc_pools_memory(vm, 0, &totals[0], &frees[0], isEnd);
418
if (isEnd) {
419
supportedMemoryPoolIDs = (U_32)mmFuncs->j9gc_allsupported_memorypools(vm);
420
for (count = 0, mask = 1, idx = 0; count < J9_GC_MANAGEMENT_MAX_POOL; ++count, mask <<= 1) {
421
id = (supportedMemoryPoolIDs & mask);
422
if (0 != id) {
423
maxs[idx] = mmFuncs->j9gc_pool_maxmemory(vm, id);
424
idx += 1;
425
}
426
}
427
gcEndEvent(vm, heapSize, heapUsed, &totals[0], &frees[0], &maxs[0], collectorID, omrVMThread);
428
} else {
429
gcStartEvent(vm, heapSize, heapUsed, &totals[0], &frees[0], collectorID);
430
}
431
}
432
433
434
static void
435
managementGlobalGCStart(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
436
{
437
MM_GlobalGCStartEvent *event = (MM_GlobalGCStartEvent *)eventData;
438
managementGC(event->currentThread, userData, FALSE);
439
}
440
static void managementGlobalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
441
{
442
MM_GlobalGCEndEvent *event = (MM_GlobalGCEndEvent *)eventData;
443
managementGC(event->currentThread, userData, TRUE);
444
}
445
static void managementLocalGCStart(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
446
{
447
MM_LocalGCStartEvent *event = (MM_LocalGCStartEvent*)eventData;
448
managementGC(event->currentThread, userData, FALSE);
449
}
450
static void managementLocalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
451
{
452
MM_LocalGCEndEvent *event = (MM_LocalGCEndEvent*)eventData;
453
managementGC(event->currentThread, userData, TRUE);
454
}
455
456
static void
457
managementCompactEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
458
{
459
J9JavaVM *vm = userData;
460
J9JavaLangManagementData *mgmt = vm->managementData;
461
UDATA idx = 0;
462
463
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
464
465
for (idx = 0; idx < (UDATA)mgmt->supportedCollectors; ++idx) {
466
if (0 == (mgmt->garbageCollectors[idx].id & J9VM_MANAGEMENT_GC_LOCAL)) {
467
mgmt->garbageCollectors[idx].totalCompacts += 1;
468
break;
469
}
470
}
471
472
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
473
}
474
475
/* Updates java.lang.management data for the start of a GC. */
476
static void
477
gcStartEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *frees, UDATA collectorID)
478
{
479
J9JavaLangManagementData *mgmt = vm->managementData;
480
J9GarbageCollectorData *gcData = &mgmt->garbageCollectors[getArrayIndexFromManagerID(mgmt, collectorID)];
481
J9MemoryPoolData *memoryPools = mgmt->memoryPools;
482
J9MemoryNotification *notification = NULL;
483
J9MemoryNotification *last = NULL;
484
J9GarbageCollectionInfo* gcInfo = NULL;
485
486
UDATA total = 0;
487
UDATA used = 0;
488
UDATA idx = 0;
489
490
PORT_ACCESS_FROM_JAVAVM(vm);
491
/* lock the management struct */
492
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
493
494
/* check the wall clock */
495
/* the start time in milliseconds since the Java virtual machine was started */
496
gcInfo = &gcData->lastGcInfo;
497
gcInfo->startTime = j9time_current_time_millis();
498
if (gcInfo->startTime < (U_64)mgmt->vmStartTime) {
499
/* startTime is earlier than vmStartTime in case of wall clock correction while interval is measuring */
500
gcInfo->startTime = 0;
501
} else {
502
gcInfo->startTime -= mgmt->vmStartTime;
503
}
504
505
mgmt->preCollectionHeapSize = heapSize;
506
mgmt->preCollectionHeapUsed = heapUsed;
507
508
for (idx = 0; idx < mgmt->supportedMemoryPools; ++idx) {
509
J9MemoryPoolData *memoryPool = &memoryPools[idx];
510
total = totals[idx];
511
used = totals[idx] - frees[idx];
512
513
/* update pre Memory Usage of last GcInfo for the collector */
514
gcInfo->preUsed[idx] = used;
515
gcInfo->preCommitted[idx] = total;
516
517
gcInfo->preMax[idx] = 0;
518
if (0 != mgmt->lastGCID) {
519
J9GarbageCollectorData *lastGcData = &mgmt->garbageCollectors[getArrayIndexFromManagerID(mgmt, mgmt->lastGCID)];
520
J9GarbageCollectionInfo* lastGcInfo = &lastGcData->lastGcInfo;
521
gcInfo->preMax[idx] = lastGcInfo->postMax[idx];
522
}
523
if (0 == gcInfo->preMax[idx]) {
524
gcInfo->preMax[idx] = memoryPool->postCollectionMaxSize;
525
}
526
527
/* check the peak usage and update */
528
if (memoryPool->peakUsed < used) {
529
memoryPool->peakUsed = used;
530
memoryPool->peakSize = total;
531
memoryPool->peakMax = gcInfo->preMax[idx];
532
}
533
534
/* if a heap usage threshold is set, check whether we are above or below */
535
if (0 < memoryPool->usageThreshold) {
536
if (memoryPool->usageThreshold < used) {
537
/* usage above threshold now, was it below threshold last time? */
538
if (0 == (memoryPool->notificationState & THRESHOLD_EXCEEDED)) {
539
540
/* if so, generate a notification and set the flag */
541
memoryPool->notificationState |= THRESHOLD_EXCEEDED;
542
memoryPool->usageThresholdCrossedCount++;
543
544
/* if the queue is full, silently discard this notification */
545
if (NOTIFICATION_QUEUE_MAX > mgmt->notificationsPending) {
546
notification = j9mem_allocate_memory(sizeof(*notification), J9MEM_CATEGORY_VM_JCL);
547
if (NULL != notification) {
548
notification->gcInfo = NULL;
549
notification->usageThreshold = j9mem_allocate_memory(sizeof(*notification->usageThreshold), J9MEM_CATEGORY_VM_JCL);
550
if (NULL == notification->usageThreshold) {
551
j9mem_free_memory(notification);
552
notification = NULL;
553
}
554
}
555
/* in case of allocation failure, silently discard the notification */
556
if (NULL != notification) {
557
/* populate the notification data */
558
notification->type = THRESHOLD_EXCEEDED;
559
notification->next = NULL;
560
notification->usageThreshold->poolID = memoryPool->id;
561
notification->usageThreshold->usedSize = used;
562
notification->usageThreshold->totalSize = total;
563
notification->usageThreshold->maxSize = gcInfo->preMax[idx];
564
notification->usageThreshold->thresholdCrossingCount = memoryPool->usageThresholdCrossedCount;
565
notification->sequenceNumber = mgmt->notificationCount++;
566
567
/* notify the thread that dispatches notifications to Java handlers */
568
omrthread_monitor_enter(mgmt->notificationMonitor);
569
570
/* find the end of the queue and count the entries */
571
last = mgmt->notificationQueue;
572
while ((last != NULL) && (last->next != NULL)) {
573
last = last->next;
574
}
575
/* add to queue */
576
if (NULL == last) {
577
mgmt->notificationQueue = notification;
578
last = notification;
579
} else {
580
last->next = notification;
581
}
582
mgmt->notificationsPending += 1;
583
584
omrthread_monitor_notify(mgmt->notificationMonitor);
585
omrthread_monitor_exit(mgmt->notificationMonitor);
586
}
587
}
588
}
589
} else {
590
/* usage below threshold now, was it above threshold last time? */
591
if (0 != (memoryPool->notificationState & THRESHOLD_EXCEEDED)) {
592
/* if so, clear the flag */
593
memoryPool->notificationState &= ~THRESHOLD_EXCEEDED;
594
}
595
}
596
}
597
}
598
599
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
600
601
/* update nonHeap memory pools for preCollection */
602
updateNonHeapMemoryPoolSizes(vm, mgmt, FALSE);
603
}
604
605
/* Updates java.lang.management data for the end of a GC. */
606
static void
607
gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *frees, UDATA *maxs, UDATA collectorID, OMR_VMThread *omrVMThread)
608
{
609
J9JavaLangManagementData *mgmt = vm->managementData;
610
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
611
J9GarbageCollectorData *gcData = &mgmt->garbageCollectors[getArrayIndexFromManagerID(mgmt, collectorID)];
612
J9MemoryPoolData *memoryPools = mgmt->memoryPools;
613
J9MemoryNotification *notification = NULL;
614
J9MemoryNotification *last = NULL;
615
616
UDATA total = 0;
617
UDATA used = 0;
618
UDATA max = 0;
619
UDATA idx = 0;
620
U_32 notificationEnabled = 0;
621
622
UDATA supportedMemoryPools = mgmt->supportedMemoryPools;
623
UDATA supportedNonHeapMemoryPools = mgmt->supportedNonHeapMemoryPools;
624
J9GarbageCollectionInfo* gcInfo = NULL;
625
626
PORT_ACCESS_FROM_JAVAVM(vm);
627
628
/* lock the management struct */
629
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
630
631
mgmt->lastGCID = (U_32)collectorID;
632
mgmt->postCollectionHeapSize = heapSize;
633
mgmt->postCollectionHeapUsed = heapUsed;
634
gcInfo = &gcData->lastGcInfo;
635
636
for (idx = 0; idx < mgmt->supportedMemoryPools; ++idx) {
637
J9MemoryPoolData *memoryPool = &memoryPools[idx];
638
total = totals[idx];
639
used = totals[idx] - frees[idx];
640
max = maxs[idx];
641
642
/* update post Memory Usage of last GcInfo for the collector */
643
gcInfo->postUsed[idx] = used;
644
gcInfo->postCommitted[idx] = total;
645
gcInfo->postMax[idx] = max;
646
647
/* check the peak usage and update */
648
if (memoryPool->peakUsed < used) {
649
memoryPool->peakUsed = used;
650
memoryPool->peakSize = total;
651
memoryPool->peakMax = max;
652
}
653
654
/* if a memory pool collection threshold is set and the memory pool is managed by the collector, check whether we are above or below */
655
if ((0 < memoryPool->collectionUsageThreshold) && mmFuncs->j9gc_is_managedpool_by_collector(vm, (UDATA)(gcData->id & J9VM_MANAGEMENT_GC_HEAP_ID_MASK), (UDATA)(memoryPool->id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK))) {
656
if (memoryPool->collectionUsageThreshold < used) {
657
/* usage above threshold now, was it below threshold last time? */
658
if (0 == (memoryPool->notificationState & COLLECTION_THRESHOLD_EXCEEDED)) {
659
660
/* if so, generate a notification and set the flag */
661
memoryPool->notificationState |= COLLECTION_THRESHOLD_EXCEEDED;
662
memoryPool->collectionUsageThresholdCrossedCount++;
663
664
/* if the queue is full, silently discard this notification */
665
if (NOTIFICATION_QUEUE_MAX > mgmt->notificationsPending) {
666
notification = j9mem_allocate_memory(sizeof(*notification), J9MEM_CATEGORY_VM_JCL);
667
/* in case of allocation failure, silently discard the notification */
668
if (NULL != notification) {
669
notification->gcInfo = NULL;
670
notification->usageThreshold = j9mem_allocate_memory(sizeof(*notification->usageThreshold), J9MEM_CATEGORY_VM_JCL);
671
if (NULL == notification->usageThreshold) {
672
j9mem_free_memory(notification);
673
notification = NULL;
674
}
675
}
676
if (NULL != notification) {
677
/* populate the notification data */
678
notification->type = COLLECTION_THRESHOLD_EXCEEDED;
679
notification->next = NULL;
680
notification->usageThreshold->poolID = memoryPool->id;
681
notification->usageThreshold->usedSize = used;
682
notification->usageThreshold->totalSize = total;
683
notification->usageThreshold->maxSize = max;
684
notification->usageThreshold->thresholdCrossingCount = memoryPool->collectionUsageThresholdCrossedCount;
685
notification->sequenceNumber = mgmt->notificationCount++;
686
687
/* notify the thread that dispatches notifications to Java handlers */
688
omrthread_monitor_enter(mgmt->notificationMonitor);
689
/* find the end of the queue and count the entries */
690
last = mgmt->notificationQueue;
691
/* find the end of the queue and count the entries */
692
while ((NULL != last) && (NULL != last->next)) {
693
last = last->next;
694
}
695
/* add to queue */
696
if (NULL == last) {
697
mgmt->notificationQueue = notification;
698
last = notification;
699
} else {
700
last->next = notification;
701
}
702
703
mgmt->notificationsPending += 1;
704
omrthread_monitor_notify(mgmt->notificationMonitor);
705
omrthread_monitor_exit(mgmt->notificationMonitor);
706
}
707
}
708
}
709
} else {
710
/* usage below threshold now, was it above threshold last time? */
711
if (0 != (memoryPool->notificationState & COLLECTION_THRESHOLD_EXCEEDED)) {
712
/* if so, clear the flag */
713
memoryPool->notificationState &= ~COLLECTION_THRESHOLD_EXCEEDED;
714
}
715
}
716
}
717
}
718
719
/* update the relevant stats */
720
/* the end time in milliseconds since the Java virtual machine was started */
721
gcData->lastGcInfo.endTime = j9time_current_time_millis();
722
if (gcData->lastGcInfo.endTime < (U_64)mgmt->vmStartTime) {
723
/* endTime is earlier than vmStartTime in case of wall clock correction while interval is measuring */
724
gcData->lastGcInfo.endTime = 0;
725
} else {
726
gcData->lastGcInfo.endTime -= mgmt->vmStartTime;
727
}
728
/* endTime is earlier than startTime in case of wall clock correction while interval is measuring */
729
if (gcData->lastGcInfo.endTime >= gcData->lastGcInfo.startTime) {
730
gcData->totalGCTime += (gcData->lastGcInfo.endTime - gcData->lastGcInfo.startTime);
731
} else {
732
gcData->lastGcInfo.endTime = gcData->lastGcInfo.startTime;
733
}
734
735
/* collectionCount */
736
gcData->lastGcInfo.index += 1;
737
gcData->memoryUsed = 0;
738
739
for (idx = 0; idx < mgmt->supportedMemoryPools; ++idx) {
740
if (0 != mmFuncs->j9gc_is_managedpool_by_collector(vm, (gcData->id & J9VM_MANAGEMENT_GC_HEAP_ID_MASK), (memoryPools[idx].id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK))) {
741
gcData->memoryUsed += memoryPools[idx].postCollectionUsed;
742
}
743
}
744
745
gcData->totalMemoryFreed += (I_64)(mgmt->preCollectionHeapUsed - mgmt->postCollectionHeapUsed);
746
747
/* update the GC CPU usage */
748
mmFuncs->j9gc_get_CPU_times(vm, &mgmt->gcMainCpuTime, &mgmt->gcWorkerCpuTime, &mgmt->gcMaxThreads, &mgmt->gcCurrentThreads);
749
750
/* update nonHeap memory pools for postCollection */
751
updateNonHeapMemoryPoolSizes(vm, mgmt, TRUE);
752
/* update J9GarbageCollectionInfo for the collector */
753
754
gcInfo->gcID = gcData->id;
755
gcInfo->gcAction = mmFuncs->j9gc_get_gc_action(vm, (gcInfo->gcID & J9VM_MANAGEMENT_GC_HEAP_ID_MASK));
756
gcInfo->gcCause = mmFuncs->j9gc_get_gc_cause(omrVMThread);
757
gcInfo->arraySize =(U_32) (supportedMemoryPools + supportedNonHeapMemoryPools);
758
/* heap memory pools */
759
for (idx = 0; supportedMemoryPools > idx; ++idx) {
760
J9MemoryPoolData *memoryPool = &memoryPools[idx];
761
gcInfo->initialSize[idx] = memoryPool->initialSize;
762
if (mmFuncs->j9gc_is_managedpool_by_collector(vm, (UDATA)(gcData->id & J9VM_MANAGEMENT_GC_HEAP_ID_MASK), (UDATA)(memoryPool->id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK))) {
763
/**
764
* the memoryPool is managed by this collection, update preCollection postCollection Memory Usage of this memory Pool
765
* gcInfo keep memory Usage before and after this gc
766
* preCollection postCollection Memory Usage in memoryPool only keep information for the GC, which recycle the memory pool
767
*/
768
memoryPool->preCollectionUsed = gcInfo->preUsed[idx];
769
memoryPool->preCollectionSize = gcInfo->preCommitted[idx];
770
memoryPool->preCollectionMaxSize = (U_64)gcInfo->preMax[idx];
771
memoryPool->postCollectionUsed = gcInfo->postUsed[idx];
772
memoryPool->postCollectionSize = gcInfo->postCommitted[idx];
773
memoryPool->postCollectionMaxSize = (U_64)gcInfo->postMax[idx];
774
}
775
}
776
/* non heap memory pools */
777
for (; supportedMemoryPools + supportedNonHeapMemoryPools > idx; ++idx) {
778
J9NonHeapMemoryData *nonHeapMemory = &mgmt->nonHeapMemoryPools[idx-supportedMemoryPools];
779
gcInfo->initialSize[idx] = nonHeapMemory->initialSize;
780
gcInfo->preUsed[idx] = nonHeapMemory->preCollectionUsed;
781
gcInfo->preCommitted[idx] = nonHeapMemory->preCollectionSize;
782
gcInfo->preMax[idx] = nonHeapMemory->maxSize;
783
gcInfo->postUsed[idx] = nonHeapMemory->postCollectionUsed;
784
gcInfo->postCommitted[idx] = nonHeapMemory->postCollectionSize;
785
gcInfo->postMax[idx] = nonHeapMemory->maxSize;
786
}
787
788
/* garbage collection notification */
789
notificationEnabled = mgmt->notificationEnabled;
790
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
791
792
if (0 !=notificationEnabled) {
793
notification = j9mem_allocate_memory(sizeof(*notification), J9MEM_CATEGORY_VM_JCL);
794
/* in case of allocation failure, silently discard the notification */
795
if (NULL != notification) {
796
notification->usageThreshold = NULL;
797
notification->gcInfo = j9mem_allocate_memory(sizeof(*notification->gcInfo), J9MEM_CATEGORY_VM_JCL);
798
if (NULL == notification->gcInfo) {
799
j9mem_free_memory(notification);
800
notification = NULL;
801
}
802
}
803
if (NULL != notification) {
804
memcpy(notification->gcInfo, gcInfo, sizeof(*notification->gcInfo));
805
806
notification->type = END_OF_GARBAGE_COLLECTION;
807
notification->next = NULL;
808
notification->sequenceNumber = mgmt->notificationCount++;
809
810
/* notify the thread that dispatches notifications to Java handlers */
811
omrthread_monitor_enter(mgmt->notificationMonitor);
812
/* find the end of the queue and count the entries */
813
last = mgmt->notificationQueue;
814
/* find the end of the queue and count the entries */
815
while ((NULL != last) && (NULL != last->next)) {
816
last = last->next;
817
}
818
/* add to queue */
819
if (NULL == last) {
820
mgmt->notificationQueue = notification;
821
last = notification;
822
} else {
823
last->next = notification;
824
}
825
826
mgmt->notificationsPending += 1;
827
omrthread_monitor_notify(mgmt->notificationMonitor);
828
omrthread_monitor_exit(mgmt->notificationMonitor);
829
}
830
}
831
}
832
833
static jint
834
initMemoryManagement(J9JavaVM *vm)
835
{
836
J9JavaLangManagementData *mgmt = vm->managementData;
837
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
838
U_32 supportedMemoryPoolIDs = (U_32)mmFuncs->j9gc_allsupported_memorypools(vm);
839
U_32 supportedCollectorIDs = (U_32)mmFuncs->j9gc_allsupported_garbagecollectors(vm);
840
U_32 id = 0;
841
U_32 mask = 0;
842
UDATA idx = 0;
843
UDATA count = 0;
844
UDATA totals[J9VM_MAX_HEAP_MEMORYPOOL_COUNT];
845
UDATA frees[J9VM_MAX_HEAP_MEMORYPOOL_COUNT];
846
U_64 used = 0;
847
J9MemorySegmentList *segList = NULL;
848
849
PORT_ACCESS_FROM_JAVAVM(vm);
850
mgmt->supportedMemoryPools = getNumberSupported(supportedMemoryPoolIDs);
851
mgmt->supportedCollectors = getNumberSupported(supportedCollectorIDs);
852
853
/* initialize Heap memory pools (initSize, maxSize) */
854
mgmt->memoryPools = j9mem_allocate_memory((sizeof(*mgmt->memoryPools) * mgmt->supportedMemoryPools), J9MEM_CATEGORY_VM_JCL);
855
if (NULL == mgmt->memoryPools) {
856
return JNI_ERR;
857
}
858
memset(mgmt->memoryPools, 0, (sizeof(*mgmt->memoryPools) * mgmt->supportedMemoryPools));
859
/* request all supported pool data for initial size */
860
mmFuncs->j9gc_pools_memory(vm, 0, &totals[0], &frees[0], FALSE);
861
862
for (count = 0, mask = 1, idx = 0; count < J9_GC_MANAGEMENT_MAX_POOL; ++count, mask <<= 1) {
863
864
id = (supportedMemoryPoolIDs & mask);
865
if (0 != id) {
866
strcpy(mgmt->memoryPools[idx].name, mmFuncs->j9gc_pool_name(vm, id));
867
mgmt->memoryPools[idx].id = (U_32) (id | J9VM_MANAGEMENT_POOL_HEAP);
868
mgmt->memoryPools[idx].initialSize = totals[idx];
869
mgmt->memoryPools[idx].preCollectionMaxSize = mmFuncs->j9gc_pool_maxmemory(vm, id);
870
mgmt->memoryPools[idx].postCollectionMaxSize = mgmt->memoryPools[idx].preCollectionMaxSize;
871
idx += 1;
872
}
873
}
874
875
/* initialize Garbage Collectors */
876
mgmt->garbageCollectors = j9mem_allocate_memory((sizeof(*mgmt->garbageCollectors) * mgmt->supportedCollectors), J9MEM_CATEGORY_VM_JCL);
877
if (NULL == mgmt->garbageCollectors) {
878
return JNI_ERR;
879
}
880
memset(mgmt->garbageCollectors, 0, (sizeof(*mgmt->garbageCollectors) * mgmt->supportedCollectors));
881
882
for (count = 0, mask = 1, idx = 0; count < J9_GC_MANAGEMENT_MAX_COLLECTOR; ++count, mask <<= 1) {
883
884
id = supportedCollectorIDs&mask;
885
if (0 != id) {
886
strcpy(mgmt->garbageCollectors[idx].name, mmFuncs->j9gc_garbagecollector_name(vm, id));
887
mgmt->garbageCollectors[idx].id = (U_32) (id | J9VM_MANAGEMENT_GC_HEAP);
888
if (mmFuncs->j9gc_is_local_collector(vm, id)) {
889
mgmt->garbageCollectors[idx].id |= J9VM_MANAGEMENT_GC_LOCAL;
890
}
891
idx += 1;
892
}
893
}
894
895
/* initialize nonHeap memory pools (initSize) */
896
mgmt->supportedNonHeapMemoryPools = 2; /* "class storage", "miscellaneous non-heap storage" */
897
#if defined( J9VM_INTERP_NATIVE_SUPPORT )
898
if (vm->jitConfig) {
899
mgmt->supportedNonHeapMemoryPools += 2; /* "JIT code cache", "JIT data cache" */
900
}
901
#endif
902
mgmt->nonHeapMemoryPools = j9mem_allocate_memory((sizeof(*mgmt->nonHeapMemoryPools) * mgmt->supportedNonHeapMemoryPools), J9MEM_CATEGORY_VM_JCL);
903
if (NULL == mgmt->nonHeapMemoryPools) {
904
return JNI_ERR;
905
}
906
memset(mgmt->nonHeapMemoryPools, 0, (sizeof(*mgmt->nonHeapMemoryPools) * mgmt->supportedNonHeapMemoryPools));
907
908
for (idx = 0; idx < mgmt->supportedNonHeapMemoryPools; idx++) {
909
switch (idx) {
910
case CLASS_MEMORY:
911
mgmt->nonHeapMemoryPools[idx].id = J9VM_MANAGEMENT_POOL_NONHEAP_SEG_CLASSES;
912
strcpy(mgmt->nonHeapMemoryPools[idx].name, J9VM_MANAGEMENT_NONHEAPPOOL_NAME_CLASSES);
913
segList = vm->classMemorySegments;
914
mgmt->nonHeapMemoryPools[idx].maxSize = -1;
915
break;
916
case MISC_MEMORY:
917
mgmt->nonHeapMemoryPools[idx].id = J9VM_MANAGEMENT_POOL_NONHEAP_SEG_MISC;
918
strcpy(mgmt->nonHeapMemoryPools[idx].name, J9VM_MANAGEMENT_NONHEAPPOOL_NAME_MISC);
919
segList = vm->memorySegments;
920
mgmt->nonHeapMemoryPools[idx].maxSize = -1;
921
break;
922
case JIT_CODECACHE:
923
mgmt->nonHeapMemoryPools[idx].id = J9VM_MANAGEMENT_POOL_NONHEAP_SEG_JIT_CODE;
924
strcpy(mgmt->nonHeapMemoryPools[idx].name, J9VM_MANAGEMENT_NONHEAPPOOL_NAME_JITCODE);
925
segList = vm->jitConfig->codeCacheList;
926
mgmt->nonHeapMemoryPools[idx].maxSize = vm->jitConfig->codeCacheTotalKB * 1024;
927
break;
928
case JIT_DATACACHE:
929
mgmt->nonHeapMemoryPools[idx].id = J9VM_MANAGEMENT_POOL_NONHEAP_SEG_JIT_DATA;
930
strcpy(mgmt->nonHeapMemoryPools[idx].name, J9VM_MANAGEMENT_NONHEAPPOOL_NAME_JITDATA);
931
segList = vm->jitConfig->dataCacheList;
932
mgmt->nonHeapMemoryPools[idx].maxSize = vm->jitConfig->dataCacheTotalKB * 1024;
933
break;
934
default:
935
/* Unreachable */
936
Assert_JCL_unreachable();
937
}
938
getSegmentSizes(vm, segList, &mgmt->nonHeapMemoryPools[idx].initialSize, &used, &mgmt->nonHeapMemoryPools[idx].peakSize, &mgmt->nonHeapMemoryPools[idx].peakUsed, (JIT_CODECACHE == idx));
939
}
940
return 0;
941
942
}
943
944
static U_32
945
getNumberSupported(U_32 supportedIDs)
946
{
947
U_32 numSupported = 0;
948
U_32 ids = supportedIDs;
949
while (0 != ids) {
950
ids &= ids - 1; /* clear the least bit set */
951
numSupported += 1;
952
}
953
return numSupported;
954
}
955
956
static UDATA
957
getArrayIndexFromManagerID(J9JavaLangManagementData *mgmt, UDATA id)
958
{
959
UDATA idx = 0;
960
961
for(; idx < mgmt->supportedCollectors; ++idx) {
962
if ((J9VM_MANAGEMENT_GC_HEAP_ID_MASK & mgmt->garbageCollectors[idx].id) == (J9VM_MANAGEMENT_GC_HEAP_ID_MASK & id)) {
963
return idx;
964
}
965
}
966
return 0;
967
}
968
969
static void
970
getSegmentSizes(J9JavaVM *javaVM, J9MemorySegmentList *segList, U_64 *storedSize, U_64 *storedUsed, U_64 *storedPeakSize, U_64 *storedPeakUsed, BOOLEAN isCodeCacheSegment)
971
{
972
U_64 used = 0;
973
U_64 committed = 0;
974
J9JavaLangManagementData *mgmt = javaVM->managementData;
975
976
omrthread_monitor_enter(segList->segmentMutex);
977
978
MEMORY_SEGMENT_LIST_DO(segList, seg)
979
if (isCodeCacheSegment) {
980
/* Set default values for warmAlloc and coldAlloc pointers */
981
UDATA warmAlloc = (UDATA)seg->heapBase;
982
UDATA coldAlloc = (UDATA)seg->heapTop;
983
984
/* The JIT code cache grows from both ends of the segment: the warmAlloc pointer upwards from the start of the segment
985
* and the coldAlloc pointer downwards from the end of the segment. The free space in a JIT code cache segment is the
986
* space between the warmAlloc and coldAlloc pointers. See compiler/runtime/OMRCodeCache.hpp, the contract with the JVM is
987
* that the address of the TR::CodeCache structure is stored at the beginning of the segment.
988
*/
989
#ifdef J9VM_INTERP_NATIVE_SUPPORT
990
UDATA *mccCodeCache = *((UDATA**)seg->heapBase);
991
if (mccCodeCache) {
992
J9JITConfig* jitConfig = javaVM->jitConfig;
993
if (jitConfig) {
994
warmAlloc = (UDATA)jitConfig->codeCacheWarmAlloc(mccCodeCache);
995
coldAlloc = (UDATA)jitConfig->codeCacheColdAlloc(mccCodeCache);
996
}
997
}
998
#endif
999
used += seg->size - (coldAlloc - warmAlloc);
1000
} else {
1001
used += seg->heapAlloc - seg->heapBase;
1002
}
1003
committed += seg->size;
1004
END_MEMORY_SEGMENT_LIST_DO(seg)
1005
1006
omrthread_monitor_exit(segList->segmentMutex);
1007
1008
omrthread_rwmutex_enter_write(mgmt->managementDataLock);
1009
*storedSize = committed;
1010
*storedUsed = used;
1011
if (used > *storedPeakUsed) {
1012
*storedPeakUsed = used;
1013
*storedPeakSize = committed;
1014
}
1015
omrthread_rwmutex_exit_write(mgmt->managementDataLock);
1016
}
1017
1018
static void
1019
updateNonHeapMemoryPoolSizes(J9JavaVM *vm, J9JavaLangManagementData *mgmt, BOOLEAN isGCEND)
1020
{
1021
U_32 idx = 0;
1022
U_64 *storedSize = NULL;
1023
U_64 *storedUsed = NULL;
1024
J9MemorySegmentList *segList = NULL;
1025
1026
for (; idx < mgmt->supportedNonHeapMemoryPools; ++idx) {
1027
switch (idx) {
1028
case CLASS_MEMORY:
1029
segList = vm->classMemorySegments;
1030
break;
1031
case MISC_MEMORY:
1032
segList = vm->memorySegments;
1033
break;
1034
case JIT_CODECACHE:
1035
segList = vm->jitConfig->codeCacheList;
1036
break;
1037
case JIT_DATACACHE:
1038
segList = vm->jitConfig->dataCacheList;
1039
break;
1040
default:
1041
/* Unreachable */
1042
Assert_JCL_unreachable();
1043
}
1044
if (isGCEND) {
1045
storedSize = &mgmt->nonHeapMemoryPools[idx].postCollectionSize;
1046
storedUsed = &mgmt->nonHeapMemoryPools[idx].postCollectionUsed;
1047
} else {
1048
storedSize = &mgmt->nonHeapMemoryPools[idx].preCollectionSize;
1049
storedUsed = &mgmt->nonHeapMemoryPools[idx].preCollectionUsed;
1050
}
1051
getSegmentSizes(vm, segList, storedSize, storedUsed, &mgmt->nonHeapMemoryPools[idx].peakSize, &mgmt->nonHeapMemoryPools[idx].peakUsed, (JIT_CODECACHE== idx));
1052
}
1053
}
1054
1055