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

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

package shark

import shark.HeapObject.HeapClass
import shark.Reference.LazyDetails
import shark.ReferenceLocationType.STATIC_FIELD
import shark.ReferencePattern.StaticFieldPattern
import shark.ValueHolder.ReferenceHolder

class ClassReferenceReader(
  graph: HeapGraph,
  referenceMatchers: List
) : ReferenceReader {
  private val staticFieldNameByClassName: Map>

  init {
    val staticFieldNameByClassName = mutableMapOf>()
    referenceMatchers.filterFor(graph).forEach { referenceMatcher ->
      val pattern = referenceMatcher.pattern
      if (pattern is StaticFieldPattern) {
        val mapOrNull = staticFieldNameByClassName[pattern.className]
        val map = if (mapOrNull != null) mapOrNull else {
          val newMap = mutableMapOf()
          staticFieldNameByClassName[pattern.className] = newMap
          newMap
        }
        map[pattern.fieldName] = referenceMatcher
      }
    }
    this.staticFieldNameByClassName = staticFieldNameByClassName
  }

  override fun read(source: HeapClass): Sequence {
    val ignoredStaticFields = staticFieldNameByClassName[source.name] ?: emptyMap()

    return source.readStaticFields().mapNotNull {  staticField ->
      // not non null: no null + no primitives.
      if (!staticField.value.isNonNullReference) {
        return@mapNotNull null
      }
      val fieldName = staticField.name
      if (fieldName == "\$staticOverhead" || fieldName == "\$classOverhead") {
        return@mapNotNull null
      }

      // Note: instead of calling staticField.value.asObjectId!! we cast holder to ReferenceHolder
      // and access value directly. This allows us to avoid unnecessary boxing of Long.
      val valueObjectId = (staticField.value.holder as ReferenceHolder).value
      val referenceMatcher = ignoredStaticFields[fieldName]

      if (referenceMatcher is IgnoredReferenceMatcher) {
        null
      } else {
        val sourceObjectId = source.objectId
        Reference(
          valueObjectId = valueObjectId,
          isLowPriority = referenceMatcher != null,
          lazyDetailsResolver = {
            LazyDetails(
              name = fieldName,
              locationClassObjectId = sourceObjectId,
              locationType = STATIC_FIELD,
              isVirtual = false,
              matchedLibraryLeak = referenceMatcher as LibraryLeakReferenceMatcher?,
            )
          }
        )
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy