FieldValuesReader.kt
TLDR
This file defines the FieldValuesReader
class, which is responsible for reading field values from an InstanceDumpRecord
object.
Methods
readValue
This method reads and returns the value of a specific field in the InstanceDumpRecord
. It takes a FieldRecord
object as a parameter and returns a ValueHolder
object.
readId
This private method reads and returns an ID value. The length of the ID is determined by the identifierByteSize
parameter.
readBoolean
This private method reads and returns a boolean value from the record.fieldValues
array.
readByte
This private method reads and returns a byte value from the record.fieldValues
array.
readInt
This private method reads and returns an integer value from the record.fieldValues
array.
readShort
This private method reads and returns a short value from the record.fieldValues
array.
readLong
This private method reads and returns a long value from the record.fieldValues
array.
readFloat
This private method reads and returns a float value by combining four bytes from the record.fieldValues
array.
readDouble
This private method reads and returns a double value by combining eight bytes from the record.fieldValues
array.
readChar
This private method reads and returns a character value from the record.fieldValues
array.
Class
FieldValuesReader
This class is responsible for reading field values from an InstanceDumpRecord
object. It has a constructor that takes an InstanceDumpRecord
object and an identifierByteSize
value. The class provides the readValue
method to read field values and a set of private methods to read specific types of values.
package shark.internal
import shark.HprofRecord.HeapDumpRecord.ObjectRecord.ClassDumpRecord.FieldRecord
import shark.HprofRecord.HeapDumpRecord.ObjectRecord.InstanceDumpRecord
import shark.PrimitiveType
import shark.PrimitiveType.BOOLEAN
import shark.PrimitiveType.BYTE
import shark.PrimitiveType.CHAR
import shark.PrimitiveType.DOUBLE
import shark.PrimitiveType.FLOAT
import shark.PrimitiveType.INT
import shark.PrimitiveType.LONG
import shark.PrimitiveType.SHORT
import shark.ValueHolder
import shark.ValueHolder.BooleanHolder
import shark.ValueHolder.ByteHolder
import shark.ValueHolder.CharHolder
import shark.ValueHolder.DoubleHolder
import shark.ValueHolder.FloatHolder
import shark.ValueHolder.IntHolder
import shark.ValueHolder.LongHolder
import shark.ValueHolder.ReferenceHolder
import shark.ValueHolder.ShortHolder
internal class FieldValuesReader(
private val record: InstanceDumpRecord,
private val identifierByteSize: Int
) {
private var position = 0
fun readValue(field: FieldRecord): ValueHolder {
return when (field.type) {
PrimitiveType.REFERENCE_HPROF_TYPE -> ReferenceHolder(readId())
BOOLEAN_TYPE -> BooleanHolder(readBoolean())
CHAR_TYPE -> CharHolder(readChar())
FLOAT_TYPE -> FloatHolder(readFloat())
DOUBLE_TYPE -> DoubleHolder(readDouble())
BYTE_TYPE -> ByteHolder(readByte())
SHORT_TYPE -> ShortHolder(readShort())
INT_TYPE -> IntHolder(readInt())
LONG_TYPE -> LongHolder(readLong())
else -> throw IllegalStateException("Unknown type ${field.type}")
}
}
private fun readId(): Long {
// As long as we don't interpret IDs, reading signed values here is fine.
return when (identifierByteSize) {
1 -> readByte().toLong()
2 -> readShort().toLong()
4 -> readInt().toLong()
8 -> readLong()
else -> throw IllegalArgumentException("ID Length must be 1, 2, 4, or 8")
}
}
private fun readBoolean(): Boolean {
val value = record.fieldValues[position]
position++
return value != 0.toByte()
}
private fun readByte(): Byte {
val value = record.fieldValues[position]
position++
return value
}
private fun readInt(): Int {
val value = record.fieldValues.readInt(position)
position += 4
return value
}
private fun readShort(): Short {
val value = record.fieldValues.readShort(position)
position += 2
return value
}
private fun readLong(): Long {
val value = record.fieldValues.readLong(position)
position += 8
return value
}
private fun readFloat(): Float {
return Float.fromBits(readInt())
}
private fun readDouble(): Double {
return Double.fromBits(readLong())
}
private fun readChar(): Char {
val string = String(record.fieldValues, position, 2, Charsets.UTF_16BE)
position += 2
return string[0]
}
companion object {
private val BOOLEAN_TYPE = BOOLEAN.hprofType
private val CHAR_TYPE = CHAR.hprofType
private val FLOAT_TYPE = FLOAT.hprofType
private val DOUBLE_TYPE = DOUBLE.hprofType
private val BYTE_TYPE = BYTE.hprofType
private val SHORT_TYPE = SHORT.hprofType
private val INT_TYPE = INT.hprofType
private val LONG_TYPE = LONG.hprofType
}
}