privatefunState.findPathsFromGcRoots():PathFindingResults{enqueueGcRoots()valshortestPathsToLeakingObjects=mutableListOf<ReferencePathNode>()visitingQueue@while(queuesNotEmpty){valnode=poll()if(leakingObjectIds.contains(node.objectId)){shortestPathsToLeakingObjects.add(node)// Found all refs, stop searching (unless computing retained size)
if(shortestPathsToLeakingObjects.size==leakingObjectIds.size()){if(computeRetainedHeapSize){listener.onEvent(StartedFindingDominators)}else{break@visitingQueue}}}valheapObject=try{graph.findObjectById(node.objectId)}catch(objectIdNotFound:IllegalArgumentException){// This should never happen (a heap should only have references to objects that exist)
// but when it does happen, let's at least display how we got there.
throwRuntimeException(graph.invalidObjectIdErrorMessage(node),objectIdNotFound)}objectReferenceReader.read(heapObject).forEach{reference->valnewNode=ChildNode(objectId=reference.valueObjectId,parent=node,lazyDetailsResolver=reference.lazyDetailsResolver)enqueue(node=newNode,isLowPriority=reference.isLowPriority,isLeafObject=reference.isLeafObject)}}returnPathFindingResults(shortestPathsToLeakingObjects,if(visitTrackerisDominated)visitTracker.dominatorTreeelsenull)}
returnsortedGcRoots(graph).asSequence().mapNotNull{(heapObject,gcRoot)->when(gcRoot){// Note: in sortedGcRoots we already filter out any java frame that has an associated
// thread. These are the remaining ones (shouldn't be any, this is just in case).
isJavaFrame->{GcRootReference(gcRoot,isLowPriority=true,matchedLibraryLeak=null)}isJniGlobal->{valreferenceMatcher=when(heapObject){isHeapClass->jniGlobalReferenceMatchers[heapObject.name]isHeapInstance->jniGlobalReferenceMatchers[heapObject.instanceClassName]isHeapObjectArray->jniGlobalReferenceMatchers[heapObject.arrayClassName]isHeapPrimitiveArray->jniGlobalReferenceMatchers[heapObject.arrayClassName]}if(referenceMatcher!isIgnoredReferenceMatcher){if(referenceMatcherisLibraryLeakReferenceMatcher){GcRootReference(gcRoot,isLowPriority=true,matchedLibraryLeak=referenceMatcher)}else{GcRootReference(gcRoot,isLowPriority=false,matchedLibraryLeak=null)}}else{null}}else->{GcRootReference(gcRoot,isLowPriority=false,matchedLibraryLeak=null)}}}