ObjectArrayReferenceReader.kt
TLDR
This file is a part of the Shark library and contains the ObjectArrayReferenceReader
class. The class implements the ReferenceReader
interface and defines a single read
method. The ObjectArrayReferenceReader
class is responsible for reading references from object arrays.
Methods
read
The read
method takes a HeapObjectArray
as a parameter and returns a sequence of Reference
objects. This method iterates over each element in the array and filters out any that are null or do not exist in the object graph. It then maps each element to a Reference
object, with the value object ID, index, and details about the reference location. The resulting sequence of Reference
objects is returned.
Classes
ObjectArrayReferenceReader
This class implements the ReferenceReader
interface and is responsible for reading references from object arrays. It provides a single method, read
, which takes a HeapObjectArray
and returns a sequence of Reference
objects. Additionally, it contains a companion object with a utility method, isSkippablePrimitiveWrapperArray
, to determine if a given array is a skippable primitive wrapper array.
package shark
import shark.HeapObject.HeapObjectArray
import shark.Reference.LazyDetails
import shark.ReferenceLocationType.ARRAY_ENTRY
internal class ObjectArrayReferenceReader : ReferenceReader<HeapObjectArray> {
override fun read(source: HeapObjectArray): Sequence<Reference> {
if (source.isSkippablePrimitiveWrapperArray) {
// primitive wrapper arrays aren't interesting.
// That also means the wrapped size isn't added to the dominator tree, so we need to
// add that back when computing shallow size in ShallowSizeCalculator.
// Another side effect is that if the wrapped primitive is referenced elsewhere, we might
// double count its size.
return emptySequence()
}
val graph = source.graph
val record = source.readRecord()
val arrayClassId = source.arrayClassId
return record.elementIds.asSequence().filter { objectId ->
objectId != ValueHolder.NULL_REFERENCE && graph.objectExists(objectId)
}.mapIndexed { index, elementObjectId ->
Reference(
valueObjectId = elementObjectId,
isLowPriority = false,
lazyDetailsResolver = {
LazyDetails(
name = index.toString(),
locationClassObjectId = arrayClassId,
locationType = ARRAY_ENTRY,
isVirtual = false,
matchedLibraryLeak = null
)
}
)
}
}
internal companion object {
private val skippablePrimitiveWrapperArrayTypes = setOf(
Boolean::class,
Char::class,
Float::class,
Double::class,
Byte::class,
Short::class,
Int::class,
Long::class
).map { it.javaObjectType.name + "[]" }
internal val HeapObjectArray.isSkippablePrimitiveWrapperArray: Boolean
get() = arrayClassName in skippablePrimitiveWrapperArrayTypes
}
}