Path: blob/master/runtime/gc_api/HeapRootScanner.cpp
5985 views
1/*******************************************************************************2* Copyright (c) 1991, 2021 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* 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 and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*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-exception21*******************************************************************************/222324#include <stdlib.h>25#include <stdio.h>26#include <limits.h> // or <climits> for CHAR_BIT27#include <string.h> // memcpy2829#include "j9cfg.h"30#include "j9.h"31#if defined(J9VM_OPT_JVMTI)32#include "jvmtiInternal.h"33#endif /* defined(J9VM_OPT_JVMTI) */3435#include "HeapRootScanner.hpp"3637#include "ClassIterator.hpp"38#include "ClassHeapIterator.hpp"39#include "ClassLoaderIterator.hpp"40#include "Debug.hpp"41#if defined(J9VM_GC_FINALIZATION)42#include "FinalizeListManager.hpp"43#endif /* J9VM_GC_FINALIZATION*/44#include "MixedObjectIterator.hpp"45#include "ModronTypes.hpp"46#include "ObjectAccessBarrier.hpp"47#include "ObjectHeapIterator.hpp"48#include "ObjectModel.hpp"49#include "OwnableSynchronizerObjectList.hpp"50#include "PointerArrayIterator.hpp"51#include "SegmentIterator.hpp"52#include "StringTable.hpp"53#include "UnfinalizedObjectList.hpp"54#include "VMClassSlotIterator.hpp"55#include "VMThreadListIterator.hpp"56#include "VMThreadIterator.hpp"5758/**59* @todo Provide function documentation60*/61void62MM_HeapRootScanner::doClassLoader(J9ClassLoader *classLoader)63{64if (J9_GC_CLASS_LOADER_DEAD != (classLoader->gcFlags & J9_GC_CLASS_LOADER_DEAD) ) {65doSlot(J9GC_J9CLASSLOADER_CLASSLOADEROBJECT_EA(classLoader));66}67}6869void70MM_HeapRootScanner::doOwnableSynchronizerObject(J9Object *objectPtr)71{72doObject(objectPtr);73}7475#if defined(J9VM_GC_FINALIZATION)76/**77* @todo Provide function documentation78*/79void80MM_HeapRootScanner::doUnfinalizedObject(J9Object *objectPtr)81{82doObject(objectPtr);83}84#endif /* J9VM_GC_FINALIZATION */8586#if defined(J9VM_GC_FINALIZATION)87/**88* @todo Provide function documentation89*/90void91MM_HeapRootScanner::doFinalizableObject(J9Object *objectPtr)92{93doObject(objectPtr);94}95#endif /* J9VM_GC_FINALIZATION */9697/**98* @todo Provide function documentation99*/100void101MM_HeapRootScanner::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)102{103J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor *)objectMonitor->monitor;104105void *userData = (void *)monitor->userData;106107doObject((J9Object *)userData);108}109110/**111* @todo Provide function documentation112*/113void114MM_HeapRootScanner::doJNIWeakGlobalReference(J9Object **slotPtr)115{116doSlot(slotPtr);117}118119#if defined(J9VM_GC_MODRON_SCAVENGER)120/**121* @todo Provide function documentation122*/123void124MM_HeapRootScanner::doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)125{126doSlot(slotPtr);127}128#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */129130/**131* @todo Provide function documentation132*/133void134MM_HeapRootScanner::doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator)135{136doSlot(slotPtr);137}138139/**140* @todo Provide function documentation141*/142void143MM_HeapRootScanner::doVMClassSlot(J9Class *classPtr)144{145doClassSlot(classPtr);146}147148#if defined(J9VM_OPT_JVMTI)149/**150* @todo Provide function documentation151*/152void153MM_HeapRootScanner::doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)154{155doSlot(slotPtr);156}157#endif /* J9VM_OPT_JVMTI */158159/**160* @todo Provide function documentation161*/162void163MM_HeapRootScanner::scanClasses()164{165#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)166J9ClassLoader *sysClassLoader = _javaVM->systemClassLoader;167J9ClassLoader *appClassLoader = _javaVM->applicationClassLoader;168MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )_extensions->dynamicClassUnloading;169#endif170171reportScanningStarted(RootScannerEntity_Classes);172173GC_SegmentIterator segmentIterator(_javaVM->classMemorySegments, MEMORY_TYPE_RAM_CLASS);174175while(J9MemorySegment *segment = segmentIterator.nextSegment()) {176GC_ClassHeapIterator classHeapIterator(_javaVM, segment);177J9Class *clazz = NULL;178while(NULL != (clazz = classHeapIterator.nextClass())) {179RootScannerEntityReachability reachability;180#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)181if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER == dynamicClassUnloadingFlag) {182/* if -Xnoclassgc, all classes are strong */183reachability = RootScannerEntityReachability_Strong;184} else {185if ((sysClassLoader == clazz->classLoader) || (appClassLoader == clazz->classLoader)) {186reachability = RootScannerEntityReachability_Strong;187} else {188reachability = RootScannerEntityReachability_Weak;189}190}191#else192reachability = RootScannerEntityReachability_Strong;193#endif194setReachability(reachability);195doClass(clazz);196}197}198199reportScanningEnded(RootScannerEntity_Classes);200}201202/**203* Scan through the slots in the VM containing known classes204*/205void206MM_HeapRootScanner::scanVMClassSlots()207{208reportScanningStarted(RootScannerEntity_VMClassSlots);209setReachability(RootScannerEntityReachability_Strong);210211GC_VMClassSlotIterator classSlotIterator(_javaVM);212J9Class *classPtr;213214while (NULL != (classPtr = classSlotIterator.nextSlot())) {215doVMClassSlot(classPtr);216}217218reportScanningEnded(RootScannerEntity_VMClassSlots);219}220221/**222* General class slot handler to be reimplemented by specializing class.223* This handler is called for every reference to a J9Class.224*/225void226MM_HeapRootScanner::doClassSlot(J9Class *classPtr)227{228doClass(classPtr);229}230231/**232* @todo Provide function documentation233*/234void235MM_HeapRootScanner::doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator)236{237doSlot(slotPtr);238}239240241/**242* @todo Provide function documentation243*/244void245MM_HeapRootScanner::doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator)246{247doSlot(slotPtr);248}249250/**251* @todo Provide function documentation252*/253void254MM_HeapRootScanner::scanClassLoaders()255{256#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)257J9ClassLoader *sysClassLoader = _javaVM->systemClassLoader;258J9ClassLoader *appClassLoader = _javaVM->applicationClassLoader;259MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )_extensions->dynamicClassUnloading;260#endif261J9ClassLoader *classLoader;262GC_ClassLoaderIterator classLoaderIterator(_javaVM->classLoaderBlocks);263264reportScanningStarted(RootScannerEntity_ClassLoaders);265266while((classLoader = classLoaderIterator.nextSlot()) != NULL) {267RootScannerEntityReachability reachability;268#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)269if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER == dynamicClassUnloadingFlag) {270/* if -Xnoclassgc, all class loader refs are strong */271reachability = RootScannerEntityReachability_Strong;272} else {273if (classLoader == appClassLoader || classLoader == sysClassLoader) {274reachability = RootScannerEntityReachability_Strong;275} else {276reachability = RootScannerEntityReachability_Weak;277}278}279#else280reachability = RootScannerEntityReachability_Strong;281#endif282setReachability(reachability);283doClassLoader(classLoader);284285}286reportScanningEnded(RootScannerEntity_ClassLoaders);287}288289/**290* @todo Provide function documentation291*292* This function iterates through all the threads, calling scanOneThread on each one that293* should be scanned. The scanOneThread function scans exactly one thread and returns294* either true (if it took an action that requires the thread list iterator to return to295* the beginning) or false (if the thread list iterator should just continue with the next296* thread).297*/298void299MM_HeapRootScanner::scanThreads()300{301reportScanningStarted(RootScannerEntity_Threads);302setReachability(RootScannerEntityReachability_Strong);303304GC_VMThreadListIterator vmThreadListIterator(_javaVM);305306while(J9VMThread *walkThread = vmThreadListIterator.nextVMThread()) {307if (scanOneThread(walkThread)) {308vmThreadListIterator.reset(_javaVM->mainThread);309}310}311312reportScanningEnded(RootScannerEntity_Threads);313}314315/**316* This function scans exactly one thread for potential roots.317* @param walkThead the thread to be scanned318* @param localData opaque data to be passed to the stack walker callback function.319* The root scanner fixes that callback function to the stackSlotIterator function320* defined above321* @return true if the thread scan included an action that requires the thread list322* iterator to begin over again at the beginning, false otherwise. This implementation323* always returns false but an overriding implementation may take actions that require324* a true return (for example, RealtimeRootScanner returns true if it yielded after the325* scan, allowing other threads to run and perhaps be created or terminated).326**/327bool328MM_HeapRootScanner::scanOneThread(J9VMThread* walkThread)329{330GC_VMThreadIterator vmThreadIterator(walkThread);331332while(J9Object **slot = vmThreadIterator.nextSlot()) {333doVMThreadSlot(slot, &vmThreadIterator);334}335336return false;337}338339#if defined(J9VM_GC_FINALIZATION)340/**341* @todo Provide function documentation342*/343void344MM_HeapRootScanner::scanFinalizableObjects()345{346reportScanningStarted(RootScannerEntity_FinalizableObjects);347setReachability(RootScannerEntityReachability_Strong);348349GC_FinalizeListManager * finalizeListManager = _extensions->finalizeListManager;350{351/* walk finalizable objects created by the system class loader */352j9object_t systemObject = finalizeListManager->peekSystemFinalizableObject();353while (NULL != systemObject) {354doFinalizableObject(systemObject);355systemObject = finalizeListManager->peekNextSystemFinalizableObject(systemObject);356}357}358359{360/* walk finalizable objects created by all other class loaders*/361j9object_t defaultObject = finalizeListManager->peekDefaultFinalizableObject();362while (NULL != defaultObject) {363doFinalizableObject(defaultObject);364defaultObject = finalizeListManager->peekNextDefaultFinalizableObject(defaultObject);365}366}367368{369/* walk reference objects */370j9object_t referenceObject = finalizeListManager->peekReferenceObject();371while (NULL != referenceObject) {372doFinalizableObject(referenceObject);373referenceObject = finalizeListManager->peekNextReferenceObject(referenceObject);374}375}376377reportScanningEnded(RootScannerEntity_FinalizableObjects);378}379#endif /* J9VM_GC_FINALIZATION */380381/**382* @todo Provide function documentation383*/384void385MM_HeapRootScanner::scanJNIGlobalReferences()386{387reportScanningStarted(RootScannerEntity_JNIGlobalReferences);388setReachability(RootScannerEntityReachability_Strong);389390GC_JNIGlobalReferenceIterator jniGlobalReferenceIterator(_javaVM->jniGlobalReferences);391J9Object **slot;392393while((slot = (J9Object **)jniGlobalReferenceIterator.nextSlot()) != NULL) {394doJNIGlobalReferenceSlot(slot, &jniGlobalReferenceIterator);395}396397reportScanningEnded(RootScannerEntity_JNIGlobalReferences);398}399400/**401* @todo Provide function documentation402*/403void404MM_HeapRootScanner::scanStringTable()405{406reportScanningStarted(RootScannerEntity_StringTable);407RootScannerEntityReachability reachability;408409if (_extensions->collectStringConstants) {410reachability = RootScannerEntityReachability_Weak;411} else {412reachability = RootScannerEntityReachability_Strong;413}414setReachability(reachability);415416MM_StringTable *stringTable = MM_GCExtensions::getExtensions(_javaVM->omrVM)->getStringTable();417for (UDATA tableIndex = 0; tableIndex < stringTable->getTableCount(); tableIndex++) {418GC_HashTableIterator stringTableIterator(stringTable->getTable(tableIndex));419J9Object **slot;420421while((slot = (J9Object **)stringTableIterator.nextSlot()) != NULL) {422doStringTableSlot(slot, NULL);423}424}425reportScanningEnded(RootScannerEntity_StringTable);426}427428#if defined(J9VM_GC_FINALIZATION)429/**430* @todo Provide function documentation431*432* @NOTE this code is not thread safe and assumes it is called in a single threaded433* manner.434*435* @NOTE this can only be used as a READ-ONLY version of the unfinalizedObjectList.436* If you need to modify elements with-in the list you will need to provide your own functionality.437* See MM_MarkingScheme::scanUnfinalizedObjects(MM_EnvironmentStandard *env) as an example438* which modifies elements with-in the list.439*/440void441MM_HeapRootScanner::scanUnfinalizedObjects()442{443reportScanningStarted(RootScannerEntity_UnfinalizedObjects);444setReachability(RootScannerEntityReachability_Weak);445446MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;447MM_UnfinalizedObjectList *unfinalizedObjectList = _extensions->unfinalizedObjectLists;448449while(NULL != unfinalizedObjectList) {450J9Object *objectPtr = unfinalizedObjectList->getHeadOfList();451while (NULL != objectPtr) {452doUnfinalizedObject(objectPtr);453objectPtr = barrier->getFinalizeLink(objectPtr);454}455unfinalizedObjectList = unfinalizedObjectList->getNextList();456}457reportScanningEnded(RootScannerEntity_UnfinalizedObjects);458}459#endif /* J9VM_GC_FINALIZATION */460461void462MM_HeapRootScanner::scanOwnableSynchronizerObjects()463{464reportScanningStarted(RootScannerEntity_OwnableSynchronizerObjects);465setReachability(RootScannerEntityReachability_Weak);466467MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;468MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectList = _extensions->getOwnableSynchronizerObjectLists();469470while(NULL != ownableSynchronizerObjectList) {471J9Object *objectPtr = ownableSynchronizerObjectList->getHeadOfList();472while (NULL != objectPtr) {473doOwnableSynchronizerObject(objectPtr);474objectPtr = barrier->getOwnableSynchronizerLink(objectPtr);475}476ownableSynchronizerObjectList = ownableSynchronizerObjectList->getNextList();477}478reportScanningEnded(RootScannerEntity_OwnableSynchronizerObjects);479}480481/**482* @todo Provide function documentation483*/484void485MM_HeapRootScanner::scanMonitorReferences()486{487reportScanningStarted(RootScannerEntity_MonitorReferences);488setReachability(RootScannerEntityReachability_Weak);489490J9ObjectMonitor *objectMonitor = NULL;491J9MonitorTableListEntry *monitorTableList = _javaVM->monitorTableList;492while (NULL != monitorTableList) {493J9HashTable *table = monitorTableList->monitorTable;494if (NULL != table) {495GC_HashTableIterator iterator(table);496while (NULL != (objectMonitor = (J9ObjectMonitor *)iterator.nextSlot())) {497doMonitorReference(objectMonitor, &iterator);498}499}500monitorTableList = monitorTableList->next;501}502503reportScanningEnded(RootScannerEntity_MonitorReferences);504}505506/**507* @todo Provide function documentation508*/509void510MM_HeapRootScanner::scanJNIWeakGlobalReferences()511{512reportScanningStarted(RootScannerEntity_JNIWeakGlobalReferences);513setReachability(RootScannerEntityReachability_Weak);514515GC_JNIWeakGlobalReferenceIterator jniWeakGlobalReferenceIterator(_javaVM->jniWeakGlobalReferences);516J9Object **slot;517518while((slot = (J9Object **)jniWeakGlobalReferenceIterator.nextSlot()) != NULL) {519doJNIWeakGlobalReference(slot);520}521522reportScanningEnded(RootScannerEntity_JNIWeakGlobalReferences);523}524525#if defined(J9VM_GC_MODRON_SCAVENGER)526/**527* @todo Provide function documentation528*/529void530MM_HeapRootScanner::scanRememberedSet()531{532reportScanningStarted(RootScannerEntity_RememberedSet);533setReachability(RootScannerEntityReachability_Weak);534535MM_SublistPuddle *puddle;536J9Object **slotPtr;537538GC_RememberedSetIterator rememberedSetIterator(&_extensions->rememberedSet);539540while((puddle = rememberedSetIterator.nextList()) != NULL) {541GC_RememberedSetSlotIterator rememberedSetSlotIterator(puddle);542while((slotPtr = (J9Object **)rememberedSetSlotIterator.nextSlot()) != NULL) {543doRememberedSetSlot(slotPtr, &rememberedSetSlotIterator);544}545}546547reportScanningEnded(RootScannerEntity_RememberedSet);548}549#endif /* J9VM_GC_MODRON_SCAVENGER */550551#if defined(J9VM_OPT_JVMTI)552/**553* Scan the JVMTI tag tables for object references554*/555void556MM_HeapRootScanner::scanJVMTIObjectTagTables()557{558reportScanningStarted(RootScannerEntity_JVMTIObjectTagTables);559setReachability(RootScannerEntityReachability_Weak);560561J9JVMTIData * jvmtiData = J9JVMTI_DATA_FROM_VM(_javaVM);562J9JVMTIEnv * jvmtiEnv;563J9Object **slotPtr;564if (NULL != jvmtiData) {565GC_JVMTIObjectTagTableListIterator objectTagTableList( jvmtiData->environments);566while(NULL != (jvmtiEnv = (J9JVMTIEnv *)objectTagTableList.nextSlot())) {567GC_JVMTIObjectTagTableIterator objectTagTableIterator(jvmtiEnv->objectTagTable);568while(NULL != (slotPtr = (J9Object **)objectTagTableIterator.nextSlot())) {569doJVMTIObjectTagSlot(slotPtr, &objectTagTableIterator);570}571}572}573574reportScanningEnded(RootScannerEntity_JVMTIObjectTagTables);575}576#endif /* J9VM_OPT_JVMTI */577578579