xref: /aosp_15_r20/external/leakcanary2/shark/src/main/java/shark/internal/ObjectArrayReferenceReader.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)

<lambda>null1 package shark.internal
2 
3 import shark.HeapObject.HeapObjectArray
4 import shark.internal.Reference.LazyDetails
5 import shark.internal.ReferenceLocationType.ARRAY_ENTRY
6 import shark.ValueHolder
7 
8 internal class ObjectArrayReferenceReader : ReferenceReader<HeapObjectArray> {
9   override fun read(source: HeapObjectArray): Sequence<Reference> {
10     if (source.isSkippablePrimitiveWrapperArray) {
11       // primitive wrapper arrays aren't interesting.
12       // That also means the wrapped size isn't added to the dominator tree, so we need to
13       // add that back when computing shallow size in ShallowSizeCalculator.
14       // Another side effect is that if the wrapped primitive is referenced elsewhere, we might
15       // double count its size.
16       return emptySequence()
17     }
18 
19     val graph = source.graph
20     val record = source.readRecord()
21     val arrayClassId = source.arrayClassId
22     return record.elementIds.asSequence().filter { objectId ->
23       objectId != ValueHolder.NULL_REFERENCE && graph.objectExists(objectId)
24     }.mapIndexed { index, elementObjectId ->
25       Reference(
26         valueObjectId = elementObjectId,
27         isLowPriority = false,
28         lazyDetailsResolver = {
29           LazyDetails(
30             name = index.toString(),
31             locationClassObjectId = arrayClassId,
32             locationType = ARRAY_ENTRY,
33             isVirtual = false,
34             matchedLibraryLeak = null
35           )
36         }
37       )
38     }
39   }
40   internal companion object {
41     private val skippablePrimitiveWrapperArrayTypes = setOf(
42       Boolean::class,
43       Char::class,
44       Float::class,
45       Double::class,
46       Byte::class,
47       Short::class,
48       Int::class,
49       Long::class
50     ).map { it.javaObjectType.name + "[]" }
51 
52     internal val HeapObjectArray.isSkippablePrimitiveWrapperArray: Boolean
53       get() = arrayClassName in skippablePrimitiveWrapperArrayTypes
54   }
55 }
56