HprofHeapGraphTest.kt
TLDR
This file contains a test class HprofHeapGraphTest
which tests finding classes and their properties in a heap graph.
Methods
setUp
This method is annotated with @Before
and is called before each test case. It initializes the hprofFile
variable by creating a new temporary file.
non system class can be found
This test case checks if a non-system class can be found in the heap graph. It uses the HprofWriter
class to create a .hprof
file with a class record and a corresponding string record. Then it opens the heap graph from the file and asserts that the class can be found by its name.
system class can be found
This test case checks if a system class can be found in the heap graph. Similar to the previous test case, it creates a .hprof
file with a class record and a corresponding string record, but this time the class is marked as a root class. It then opens the heap graph from the file and asserts that the class can be found by its name.
system class prioritized over non system class
This test case checks if a system class is prioritized over a non-system class when both are present in the heap graph. It creates a .hprof
file with multiple class records, including a root system class and non-root non-system classes. It then opens the heap graph from the file and asserts that the system class is prioritized by checking its object ID.
Classes
HprofHeapGraphTest
This class contains test cases for finding classes in a heap graph. It uses the HprofWriter
class and its helper methods to create a .hprof
file to test against. The test cases use TemporaryFolder
rule to create a temporary directory and file for the .hprof
file.
package shark
import java.io.File
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import shark.GcRoot.StickyClass
import shark.HprofHeapGraph.Companion.openHeapGraph
import shark.HprofRecord.HeapDumpRecord.GcRootRecord
import shark.HprofRecord.HeapDumpRecord.ObjectRecord.ClassDumpRecord
import shark.HprofRecord.LoadClassRecord
import shark.HprofRecord.StringRecord
class HprofHeapGraphTest {
@get:Rule
val testFolder = TemporaryFolder()
private lateinit var hprofFile: File
@Before
fun setUp() {
hprofFile = testFolder.newFile("temp.hprof")
}
@Test
fun `non system class can be found`() {
val className = "com.example.SimpleClass"
HprofWriter.openWriterFor(hprofFile).use { writer ->
val classNameRecord = StringRecord(1L, className)
writer.write(classNameRecord)
writer.writeClass(42, classNameRecord, rootClass = false)
}
hprofFile.openHeapGraph().use { graph ->
assertThat(graph.findClassByName(className)).isNotNull
}
}
@Test
fun `system class can be found`() {
val className = "com.example.SimpleClass"
HprofWriter.openWriterFor(hprofFile).use { writer ->
val classNameRecord = StringRecord(1L, className)
writer.write(classNameRecord)
writer.writeClass(42, classNameRecord, rootClass = true)
}
hprofFile.openHeapGraph().use { graph ->
assertThat(graph.findClassByName(className)).isNotNull
}
}
@Test
fun `system class prioritized over non system class`() {
val className = "com.example.SimpleClass"
HprofWriter.openWriterFor(hprofFile).use { writer ->
val classNameRecord = StringRecord(1L, className)
writer.write(classNameRecord)
writer.writeClass(24, classNameRecord, rootClass = false)
writer.writeClass(25, classNameRecord, rootClass = false)
writer.writeClass(42, classNameRecord, rootClass = true)
writer.writeClass(43, classNameRecord, rootClass = false)
}
hprofFile.openHeapGraph().use { graph ->
val heapClass = graph.findClassByName(className)!!
assertThat(heapClass.objectId).isEqualTo(42)
}
}
private fun HprofWriter.writeClass(
classId: Long,
classNameRecord: StringRecord,
rootClass: Boolean
) {
val loadClass = LoadClassRecord(1, classId, 1, classNameRecord.id)
val classDump = ClassDumpRecord(
id = loadClass.id,
stackTraceSerialNumber = 1,
superclassId = 0,
classLoaderId = 0,
signersId = 0,
protectionDomainId = 0,
instanceSize = 0,
staticFields = emptyList(),
fields = emptyList()
)
write(loadClass)
if (rootClass) {
write(GcRootRecord(gcRoot = StickyClass(classId)))
}
write(classDump)
}
}