Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_api/HeapRootScanner.cpp
5985 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2021 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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
22
*******************************************************************************/
23
24
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <limits.h> // or <climits> for CHAR_BIT
28
#include <string.h> // memcpy
29
30
#include "j9cfg.h"
31
#include "j9.h"
32
#if defined(J9VM_OPT_JVMTI)
33
#include "jvmtiInternal.h"
34
#endif /* defined(J9VM_OPT_JVMTI) */
35
36
#include "HeapRootScanner.hpp"
37
38
#include "ClassIterator.hpp"
39
#include "ClassHeapIterator.hpp"
40
#include "ClassLoaderIterator.hpp"
41
#include "Debug.hpp"
42
#if defined(J9VM_GC_FINALIZATION)
43
#include "FinalizeListManager.hpp"
44
#endif /* J9VM_GC_FINALIZATION*/
45
#include "MixedObjectIterator.hpp"
46
#include "ModronTypes.hpp"
47
#include "ObjectAccessBarrier.hpp"
48
#include "ObjectHeapIterator.hpp"
49
#include "ObjectModel.hpp"
50
#include "OwnableSynchronizerObjectList.hpp"
51
#include "PointerArrayIterator.hpp"
52
#include "SegmentIterator.hpp"
53
#include "StringTable.hpp"
54
#include "UnfinalizedObjectList.hpp"
55
#include "VMClassSlotIterator.hpp"
56
#include "VMThreadListIterator.hpp"
57
#include "VMThreadIterator.hpp"
58
59
/**
60
* @todo Provide function documentation
61
*/
62
void
63
MM_HeapRootScanner::doClassLoader(J9ClassLoader *classLoader)
64
{
65
if (J9_GC_CLASS_LOADER_DEAD != (classLoader->gcFlags & J9_GC_CLASS_LOADER_DEAD) ) {
66
doSlot(J9GC_J9CLASSLOADER_CLASSLOADEROBJECT_EA(classLoader));
67
}
68
}
69
70
void
71
MM_HeapRootScanner::doOwnableSynchronizerObject(J9Object *objectPtr)
72
{
73
doObject(objectPtr);
74
}
75
76
#if defined(J9VM_GC_FINALIZATION)
77
/**
78
* @todo Provide function documentation
79
*/
80
void
81
MM_HeapRootScanner::doUnfinalizedObject(J9Object *objectPtr)
82
{
83
doObject(objectPtr);
84
}
85
#endif /* J9VM_GC_FINALIZATION */
86
87
#if defined(J9VM_GC_FINALIZATION)
88
/**
89
* @todo Provide function documentation
90
*/
91
void
92
MM_HeapRootScanner::doFinalizableObject(J9Object *objectPtr)
93
{
94
doObject(objectPtr);
95
}
96
#endif /* J9VM_GC_FINALIZATION */
97
98
/**
99
* @todo Provide function documentation
100
*/
101
void
102
MM_HeapRootScanner::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)
103
{
104
J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor *)objectMonitor->monitor;
105
106
void *userData = (void *)monitor->userData;
107
108
doObject((J9Object *)userData);
109
}
110
111
/**
112
* @todo Provide function documentation
113
*/
114
void
115
MM_HeapRootScanner::doJNIWeakGlobalReference(J9Object **slotPtr)
116
{
117
doSlot(slotPtr);
118
}
119
120
#if defined(J9VM_GC_MODRON_SCAVENGER)
121
/**
122
* @todo Provide function documentation
123
*/
124
void
125
MM_HeapRootScanner::doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)
126
{
127
doSlot(slotPtr);
128
}
129
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
130
131
/**
132
* @todo Provide function documentation
133
*/
134
void
135
MM_HeapRootScanner::doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator)
136
{
137
doSlot(slotPtr);
138
}
139
140
/**
141
* @todo Provide function documentation
142
*/
143
void
144
MM_HeapRootScanner::doVMClassSlot(J9Class *classPtr)
145
{
146
doClassSlot(classPtr);
147
}
148
149
#if defined(J9VM_OPT_JVMTI)
150
/**
151
* @todo Provide function documentation
152
*/
153
void
154
MM_HeapRootScanner::doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)
155
{
156
doSlot(slotPtr);
157
}
158
#endif /* J9VM_OPT_JVMTI */
159
160
/**
161
* @todo Provide function documentation
162
*/
163
void
164
MM_HeapRootScanner::scanClasses()
165
{
166
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
167
J9ClassLoader *sysClassLoader = _javaVM->systemClassLoader;
168
J9ClassLoader *appClassLoader = _javaVM->applicationClassLoader;
169
MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )_extensions->dynamicClassUnloading;
170
#endif
171
172
reportScanningStarted(RootScannerEntity_Classes);
173
174
GC_SegmentIterator segmentIterator(_javaVM->classMemorySegments, MEMORY_TYPE_RAM_CLASS);
175
176
while(J9MemorySegment *segment = segmentIterator.nextSegment()) {
177
GC_ClassHeapIterator classHeapIterator(_javaVM, segment);
178
J9Class *clazz = NULL;
179
while(NULL != (clazz = classHeapIterator.nextClass())) {
180
RootScannerEntityReachability reachability;
181
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
182
if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER == dynamicClassUnloadingFlag) {
183
/* if -Xnoclassgc, all classes are strong */
184
reachability = RootScannerEntityReachability_Strong;
185
} else {
186
if ((sysClassLoader == clazz->classLoader) || (appClassLoader == clazz->classLoader)) {
187
reachability = RootScannerEntityReachability_Strong;
188
} else {
189
reachability = RootScannerEntityReachability_Weak;
190
}
191
}
192
#else
193
reachability = RootScannerEntityReachability_Strong;
194
#endif
195
setReachability(reachability);
196
doClass(clazz);
197
}
198
}
199
200
reportScanningEnded(RootScannerEntity_Classes);
201
}
202
203
/**
204
* Scan through the slots in the VM containing known classes
205
*/
206
void
207
MM_HeapRootScanner::scanVMClassSlots()
208
{
209
reportScanningStarted(RootScannerEntity_VMClassSlots);
210
setReachability(RootScannerEntityReachability_Strong);
211
212
GC_VMClassSlotIterator classSlotIterator(_javaVM);
213
J9Class *classPtr;
214
215
while (NULL != (classPtr = classSlotIterator.nextSlot())) {
216
doVMClassSlot(classPtr);
217
}
218
219
reportScanningEnded(RootScannerEntity_VMClassSlots);
220
}
221
222
/**
223
* General class slot handler to be reimplemented by specializing class.
224
* This handler is called for every reference to a J9Class.
225
*/
226
void
227
MM_HeapRootScanner::doClassSlot(J9Class *classPtr)
228
{
229
doClass(classPtr);
230
}
231
232
/**
233
* @todo Provide function documentation
234
*/
235
void
236
MM_HeapRootScanner::doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator)
237
{
238
doSlot(slotPtr);
239
}
240
241
242
/**
243
* @todo Provide function documentation
244
*/
245
void
246
MM_HeapRootScanner::doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator)
247
{
248
doSlot(slotPtr);
249
}
250
251
/**
252
* @todo Provide function documentation
253
*/
254
void
255
MM_HeapRootScanner::scanClassLoaders()
256
{
257
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
258
J9ClassLoader *sysClassLoader = _javaVM->systemClassLoader;
259
J9ClassLoader *appClassLoader = _javaVM->applicationClassLoader;
260
MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )_extensions->dynamicClassUnloading;
261
#endif
262
J9ClassLoader *classLoader;
263
GC_ClassLoaderIterator classLoaderIterator(_javaVM->classLoaderBlocks);
264
265
reportScanningStarted(RootScannerEntity_ClassLoaders);
266
267
while((classLoader = classLoaderIterator.nextSlot()) != NULL) {
268
RootScannerEntityReachability reachability;
269
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
270
if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER == dynamicClassUnloadingFlag) {
271
/* if -Xnoclassgc, all class loader refs are strong */
272
reachability = RootScannerEntityReachability_Strong;
273
} else {
274
if (classLoader == appClassLoader || classLoader == sysClassLoader) {
275
reachability = RootScannerEntityReachability_Strong;
276
} else {
277
reachability = RootScannerEntityReachability_Weak;
278
}
279
}
280
#else
281
reachability = RootScannerEntityReachability_Strong;
282
#endif
283
setReachability(reachability);
284
doClassLoader(classLoader);
285
286
}
287
reportScanningEnded(RootScannerEntity_ClassLoaders);
288
}
289
290
/**
291
* @todo Provide function documentation
292
*
293
* This function iterates through all the threads, calling scanOneThread on each one that
294
* should be scanned. The scanOneThread function scans exactly one thread and returns
295
* either true (if it took an action that requires the thread list iterator to return to
296
* the beginning) or false (if the thread list iterator should just continue with the next
297
* thread).
298
*/
299
void
300
MM_HeapRootScanner::scanThreads()
301
{
302
reportScanningStarted(RootScannerEntity_Threads);
303
setReachability(RootScannerEntityReachability_Strong);
304
305
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
306
307
while(J9VMThread *walkThread = vmThreadListIterator.nextVMThread()) {
308
if (scanOneThread(walkThread)) {
309
vmThreadListIterator.reset(_javaVM->mainThread);
310
}
311
}
312
313
reportScanningEnded(RootScannerEntity_Threads);
314
}
315
316
/**
317
* This function scans exactly one thread for potential roots.
318
* @param walkThead the thread to be scanned
319
* @param localData opaque data to be passed to the stack walker callback function.
320
* The root scanner fixes that callback function to the stackSlotIterator function
321
* defined above
322
* @return true if the thread scan included an action that requires the thread list
323
* iterator to begin over again at the beginning, false otherwise. This implementation
324
* always returns false but an overriding implementation may take actions that require
325
* a true return (for example, RealtimeRootScanner returns true if it yielded after the
326
* scan, allowing other threads to run and perhaps be created or terminated).
327
**/
328
bool
329
MM_HeapRootScanner::scanOneThread(J9VMThread* walkThread)
330
{
331
GC_VMThreadIterator vmThreadIterator(walkThread);
332
333
while(J9Object **slot = vmThreadIterator.nextSlot()) {
334
doVMThreadSlot(slot, &vmThreadIterator);
335
}
336
337
return false;
338
}
339
340
#if defined(J9VM_GC_FINALIZATION)
341
/**
342
* @todo Provide function documentation
343
*/
344
void
345
MM_HeapRootScanner::scanFinalizableObjects()
346
{
347
reportScanningStarted(RootScannerEntity_FinalizableObjects);
348
setReachability(RootScannerEntityReachability_Strong);
349
350
GC_FinalizeListManager * finalizeListManager = _extensions->finalizeListManager;
351
{
352
/* walk finalizable objects created by the system class loader */
353
j9object_t systemObject = finalizeListManager->peekSystemFinalizableObject();
354
while (NULL != systemObject) {
355
doFinalizableObject(systemObject);
356
systemObject = finalizeListManager->peekNextSystemFinalizableObject(systemObject);
357
}
358
}
359
360
{
361
/* walk finalizable objects created by all other class loaders*/
362
j9object_t defaultObject = finalizeListManager->peekDefaultFinalizableObject();
363
while (NULL != defaultObject) {
364
doFinalizableObject(defaultObject);
365
defaultObject = finalizeListManager->peekNextDefaultFinalizableObject(defaultObject);
366
}
367
}
368
369
{
370
/* walk reference objects */
371
j9object_t referenceObject = finalizeListManager->peekReferenceObject();
372
while (NULL != referenceObject) {
373
doFinalizableObject(referenceObject);
374
referenceObject = finalizeListManager->peekNextReferenceObject(referenceObject);
375
}
376
}
377
378
reportScanningEnded(RootScannerEntity_FinalizableObjects);
379
}
380
#endif /* J9VM_GC_FINALIZATION */
381
382
/**
383
* @todo Provide function documentation
384
*/
385
void
386
MM_HeapRootScanner::scanJNIGlobalReferences()
387
{
388
reportScanningStarted(RootScannerEntity_JNIGlobalReferences);
389
setReachability(RootScannerEntityReachability_Strong);
390
391
GC_JNIGlobalReferenceIterator jniGlobalReferenceIterator(_javaVM->jniGlobalReferences);
392
J9Object **slot;
393
394
while((slot = (J9Object **)jniGlobalReferenceIterator.nextSlot()) != NULL) {
395
doJNIGlobalReferenceSlot(slot, &jniGlobalReferenceIterator);
396
}
397
398
reportScanningEnded(RootScannerEntity_JNIGlobalReferences);
399
}
400
401
/**
402
* @todo Provide function documentation
403
*/
404
void
405
MM_HeapRootScanner::scanStringTable()
406
{
407
reportScanningStarted(RootScannerEntity_StringTable);
408
RootScannerEntityReachability reachability;
409
410
if (_extensions->collectStringConstants) {
411
reachability = RootScannerEntityReachability_Weak;
412
} else {
413
reachability = RootScannerEntityReachability_Strong;
414
}
415
setReachability(reachability);
416
417
MM_StringTable *stringTable = MM_GCExtensions::getExtensions(_javaVM->omrVM)->getStringTable();
418
for (UDATA tableIndex = 0; tableIndex < stringTable->getTableCount(); tableIndex++) {
419
GC_HashTableIterator stringTableIterator(stringTable->getTable(tableIndex));
420
J9Object **slot;
421
422
while((slot = (J9Object **)stringTableIterator.nextSlot()) != NULL) {
423
doStringTableSlot(slot, NULL);
424
}
425
}
426
reportScanningEnded(RootScannerEntity_StringTable);
427
}
428
429
#if defined(J9VM_GC_FINALIZATION)
430
/**
431
* @todo Provide function documentation
432
*
433
* @NOTE this code is not thread safe and assumes it is called in a single threaded
434
* manner.
435
*
436
* @NOTE this can only be used as a READ-ONLY version of the unfinalizedObjectList.
437
* If you need to modify elements with-in the list you will need to provide your own functionality.
438
* See MM_MarkingScheme::scanUnfinalizedObjects(MM_EnvironmentStandard *env) as an example
439
* which modifies elements with-in the list.
440
*/
441
void
442
MM_HeapRootScanner::scanUnfinalizedObjects()
443
{
444
reportScanningStarted(RootScannerEntity_UnfinalizedObjects);
445
setReachability(RootScannerEntityReachability_Weak);
446
447
MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;
448
MM_UnfinalizedObjectList *unfinalizedObjectList = _extensions->unfinalizedObjectLists;
449
450
while(NULL != unfinalizedObjectList) {
451
J9Object *objectPtr = unfinalizedObjectList->getHeadOfList();
452
while (NULL != objectPtr) {
453
doUnfinalizedObject(objectPtr);
454
objectPtr = barrier->getFinalizeLink(objectPtr);
455
}
456
unfinalizedObjectList = unfinalizedObjectList->getNextList();
457
}
458
reportScanningEnded(RootScannerEntity_UnfinalizedObjects);
459
}
460
#endif /* J9VM_GC_FINALIZATION */
461
462
void
463
MM_HeapRootScanner::scanOwnableSynchronizerObjects()
464
{
465
reportScanningStarted(RootScannerEntity_OwnableSynchronizerObjects);
466
setReachability(RootScannerEntityReachability_Weak);
467
468
MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;
469
MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectList = _extensions->getOwnableSynchronizerObjectLists();
470
471
while(NULL != ownableSynchronizerObjectList) {
472
J9Object *objectPtr = ownableSynchronizerObjectList->getHeadOfList();
473
while (NULL != objectPtr) {
474
doOwnableSynchronizerObject(objectPtr);
475
objectPtr = barrier->getOwnableSynchronizerLink(objectPtr);
476
}
477
ownableSynchronizerObjectList = ownableSynchronizerObjectList->getNextList();
478
}
479
reportScanningEnded(RootScannerEntity_OwnableSynchronizerObjects);
480
}
481
482
/**
483
* @todo Provide function documentation
484
*/
485
void
486
MM_HeapRootScanner::scanMonitorReferences()
487
{
488
reportScanningStarted(RootScannerEntity_MonitorReferences);
489
setReachability(RootScannerEntityReachability_Weak);
490
491
J9ObjectMonitor *objectMonitor = NULL;
492
J9MonitorTableListEntry *monitorTableList = _javaVM->monitorTableList;
493
while (NULL != monitorTableList) {
494
J9HashTable *table = monitorTableList->monitorTable;
495
if (NULL != table) {
496
GC_HashTableIterator iterator(table);
497
while (NULL != (objectMonitor = (J9ObjectMonitor *)iterator.nextSlot())) {
498
doMonitorReference(objectMonitor, &iterator);
499
}
500
}
501
monitorTableList = monitorTableList->next;
502
}
503
504
reportScanningEnded(RootScannerEntity_MonitorReferences);
505
}
506
507
/**
508
* @todo Provide function documentation
509
*/
510
void
511
MM_HeapRootScanner::scanJNIWeakGlobalReferences()
512
{
513
reportScanningStarted(RootScannerEntity_JNIWeakGlobalReferences);
514
setReachability(RootScannerEntityReachability_Weak);
515
516
GC_JNIWeakGlobalReferenceIterator jniWeakGlobalReferenceIterator(_javaVM->jniWeakGlobalReferences);
517
J9Object **slot;
518
519
while((slot = (J9Object **)jniWeakGlobalReferenceIterator.nextSlot()) != NULL) {
520
doJNIWeakGlobalReference(slot);
521
}
522
523
reportScanningEnded(RootScannerEntity_JNIWeakGlobalReferences);
524
}
525
526
#if defined(J9VM_GC_MODRON_SCAVENGER)
527
/**
528
* @todo Provide function documentation
529
*/
530
void
531
MM_HeapRootScanner::scanRememberedSet()
532
{
533
reportScanningStarted(RootScannerEntity_RememberedSet);
534
setReachability(RootScannerEntityReachability_Weak);
535
536
MM_SublistPuddle *puddle;
537
J9Object **slotPtr;
538
539
GC_RememberedSetIterator rememberedSetIterator(&_extensions->rememberedSet);
540
541
while((puddle = rememberedSetIterator.nextList()) != NULL) {
542
GC_RememberedSetSlotIterator rememberedSetSlotIterator(puddle);
543
while((slotPtr = (J9Object **)rememberedSetSlotIterator.nextSlot()) != NULL) {
544
doRememberedSetSlot(slotPtr, &rememberedSetSlotIterator);
545
}
546
}
547
548
reportScanningEnded(RootScannerEntity_RememberedSet);
549
}
550
#endif /* J9VM_GC_MODRON_SCAVENGER */
551
552
#if defined(J9VM_OPT_JVMTI)
553
/**
554
* Scan the JVMTI tag tables for object references
555
*/
556
void
557
MM_HeapRootScanner::scanJVMTIObjectTagTables()
558
{
559
reportScanningStarted(RootScannerEntity_JVMTIObjectTagTables);
560
setReachability(RootScannerEntityReachability_Weak);
561
562
J9JVMTIData * jvmtiData = J9JVMTI_DATA_FROM_VM(_javaVM);
563
J9JVMTIEnv * jvmtiEnv;
564
J9Object **slotPtr;
565
if (NULL != jvmtiData) {
566
GC_JVMTIObjectTagTableListIterator objectTagTableList( jvmtiData->environments);
567
while(NULL != (jvmtiEnv = (J9JVMTIEnv *)objectTagTableList.nextSlot())) {
568
GC_JVMTIObjectTagTableIterator objectTagTableIterator(jvmtiEnv->objectTagTable);
569
while(NULL != (slotPtr = (J9Object **)objectTagTableIterator.nextSlot())) {
570
doJVMTIObjectTagSlot(slotPtr, &objectTagTableIterator);
571
}
572
}
573
}
574
575
reportScanningEnded(RootScannerEntity_JVMTIObjectTagTables);
576
}
577
#endif /* J9VM_OPT_JVMTI */
578
579