[New IC] Optimize Java class snapshotting with ASM ClassWriter

To snapshot a Java class (+ its fields and methods), previously we used
Gson to serialize a class field/method to a string via reflection, and
hash that string.

We now use an ASM ClassWriter to write a placeholder class containing
the field/method of interest and hash the bytecode of that class.

One experiment showed that this new approach is ~10 times faster than
the previous approach (140s down to 16s when snapshotting 600 jars).

Test: Updated expectation files for JavaClassSnapshotterTest unit tests
      + Existing integration tests to prevent regression

^KT-52141 In Progress
This commit is contained in:
Hung Nguyen
2022-04-21 16:43:58 +01:00
committed by teamcity
parent 5a0c3920a5
commit 9eb3c7ed76
8 changed files with 74 additions and 96 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.incremental.classpathDiff
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.readBytes
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.snapshot
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.JavaSourceFile
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.KotlinSourceFile
@@ -101,18 +100,10 @@ class JavaOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() {
JavaSourceFile(baseDir = File("$testDataDir/java/$testName/src"), relativePath = relativePath), tmpDir
)
private fun TestSourceFile.compileAndSnapshotWithDebugInfo(): ClassSnapshot {
val classFile = compileSingle()
return ClassSnapshotter.snapshot(
listOf(ClassFileWithContents(classFile, classFile.readBytes())),
includeDebugInfoInJavaSnapshot = true
).single()
}
@Test
fun testSimpleClass() {
val sourceFile = getSourceFile("testSimpleClass", "com/example/SimpleClass.java")
val actualSnapshot = sourceFile.compileAndSnapshotWithDebugInfo().toGson()
val actualSnapshot = sourceFile.compileAndSnapshot().toGson()
val expectedSnapshot = sourceFile.getExpectedSnapshotFile().readText()
assertEquals(expectedSnapshot, actualSnapshot)