
kshark.internal.AndroidNativeSizeMapper.kt Maven / Gradle / Ivy
package kshark.internal
import kshark.HeapGraph
import kshark.HeapObject.HeapInstance
internal class AndroidNativeSizeMapper(private val graph: HeapGraph) {
/**
* Returns a map of Object id to native size as tracked by NativeAllocationRegistry$CleanerThunk
*/
fun mapNativeSizes(): Map {
val nativeSizes = mutableMapOf()
// Doc from perflib:
// Native allocations can be identified by looking at instances of
// libcore.util.NativeAllocationRegistry$CleanerThunk. The "owning" Java object is the
// "referent" field of the "sun.misc.Cleaner" instance with a hard reference to the
// CleanerThunk.
//
// The size is in the 'size' field of the libcore.util.NativeAllocationRegistry instance
// that the CleanerThunk has a pointer to. The native pointer is in the 'nativePtr' field of
// the CleanerThunk. The hprof does not include the native bytes pointed to.
graph.findClassByName("sun.misc.Cleaner")?.let { cleanerClass ->
cleanerClass.directInstances.forEach { cleaner ->
val thunkField = cleaner["sun.misc.Cleaner", "thunk"]
val thunkId = thunkField?.value?.asNonNullObjectId
val referentId =
cleaner["java.lang.ref.Reference", "referent"]?.value?.asNonNullObjectId
if (thunkId != null && referentId != null) {
val thunkRecord = thunkField.value.asObject
if (thunkRecord is HeapInstance && thunkRecord instanceOf "libcore.util.NativeAllocationRegistry\$CleanerThunk") {
val allocationRegistryIdField =
thunkRecord["libcore.util.NativeAllocationRegistry\$CleanerThunk", "this\$0"]
if (allocationRegistryIdField != null && allocationRegistryIdField.value.isNonNullReference) {
val allocationRegistryRecord = allocationRegistryIdField.value.asObject
if (allocationRegistryRecord is HeapInstance && allocationRegistryRecord instanceOf "libcore.util.NativeAllocationRegistry") {
var nativeSize = nativeSizes[referentId] ?: 0
nativeSize += allocationRegistryRecord["libcore.util.NativeAllocationRegistry", "size"]?.value?.asLong?.toInt()
?: 0
nativeSizes[referentId] = nativeSize
}
}
}
}
}
}
return nativeSizes
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy