All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.shark.JavaLocalReferenceReader.kt Maven / Gradle / Ivy

package shark

import shark.ChainingInstanceReferenceReader.VirtualInstanceReferenceReader
import shark.HeapObject.HeapInstance
import shark.Reference.LazyDetails
import shark.ReferenceLocationType.LOCAL
import shark.ReferencePattern.JavaLocalPattern
import shark.internal.JavaFrames
import shark.internal.ThreadObjects

class JavaLocalReferenceReader(
  val graph: HeapGraph,
  referenceMatchers: List
) : VirtualInstanceReferenceReader {

  private val threadClassObjectIds: Set =
    graph.findClassByName(Thread::class.java.name)?.let { threadClass ->
      setOf(threadClass.objectId) + (threadClass.subclasses
        .map { it.objectId }
        .toSet())
    }?: emptySet()

  private val threadNameReferenceMatchers: Map

  init {
    val threadNames = mutableMapOf()
    referenceMatchers.filterFor(graph).forEach { referenceMatcher ->
      val pattern = referenceMatcher.pattern
      if (pattern is JavaLocalPattern) {
        threadNames[pattern.threadName] = referenceMatcher
      }
    }
    this.threadNameReferenceMatchers = threadNames
  }

  override fun matches(instance: HeapInstance): Boolean {
    return instance.instanceClassId in threadClassObjectIds &&
      ThreadObjects.getByThreadObjectId(graph, instance.objectId) != null
  }

  override val readsCutSet = false

  override fun read(source: HeapInstance): Sequence {
    val referenceMatcher =  source[Thread::class, "name"]?.value?.readAsJavaString()?.let { threadName ->
      threadNameReferenceMatchers[threadName]
    }

    if (referenceMatcher is IgnoredReferenceMatcher) {
      return emptySequence()
    }
    val threadClassId = source.instanceClassId
    return JavaFrames.getByThreadObjectId(graph, source.objectId)?.let { frames ->
      frames.asSequence().map { frame ->
        Reference(
          valueObjectId = frame.id,
          // Java Frames always have low priority because their path is harder to understand
          // for developers
          isLowPriority = true,
          lazyDetailsResolver = {
            LazyDetails(
              // Unfortunately Android heap dumps do not include stack trace data, so
              // JavaFrame.frameNumber is always -1 and we cannot know which method is causing the
              // reference to be held.
              name = "",
              locationClassObjectId = threadClassId,
              locationType = LOCAL,
              matchedLibraryLeak = referenceMatcher as LibraryLeakReferenceMatcher?,
              isVirtual = true
            )
          }
        )
      }
    } ?: emptySequence()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy