Build: Use only @Exported & whitelisted classes for tools.jar api

This makes it stable between JDK vendors and versions
This commit is contained in:
Vyacheslav Gerasimov
2020-11-16 03:45:21 +03:00
parent ac851523d8
commit d7474bb2f7
+34 -38
View File
@@ -1,8 +1,5 @@
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE
import org.jetbrains.org.objectweb.asm.ClassVisitor
import org.jetbrains.org.objectweb.asm.ClassWriter
import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Opcodes.*
import java.util.zip.ZipFile import java.util.zip.ZipFile
@@ -20,11 +17,9 @@ val runtimeElements by configurations.creating {
val JDK_18: String by rootProject.extra val JDK_18: String by rootProject.extra
val toolsJarFile = toolsJarFile(jdkHome = File(JDK_18)) ?: error("Couldn't find tools.jar in $JDK_18") val toolsJarFile = toolsJarFile(jdkHome = File(JDK_18)) ?: error("Couldn't find tools.jar in $JDK_18")
val usedInternalApiPackages = listOf(
// tools.jar from JDK has different public api on different platforms which makes impossible to reuse caches "com/sun/tools/javac" // Used in KAPT
// for tasks which depend on it. Since we can't compile against those classes & stay cross-platform anyway, )
// we may just exclude them from compile classpath. Since method bodies are not required for compilation
// strip them out to remove noise between different versions.
val toolsJarStubs by tasks.registering { val toolsJarStubs by tasks.registering {
inputs.file(toolsJarFile) inputs.file(toolsJarFile)
@@ -33,6 +28,7 @@ val toolsJarStubs by tasks.registering {
outputs.dir(outDir) outputs.dir(outDir)
doLast { doLast {
outDir.deleteRecursively()
val zipFile = ZipFile(toolsJarFile) val zipFile = ZipFile(toolsJarFile)
zipFile.stream() zipFile.stream()
.filter { it.name.endsWith(".class") } .filter { it.name.endsWith(".class") }
@@ -40,12 +36,37 @@ val toolsJarStubs by tasks.registering {
zipFile.getInputStream(zipEntry).use { entryStream -> zipFile.getInputStream(zipEntry).use { entryStream ->
val classReader = ClassReader(entryStream) val classReader = ClassReader(entryStream)
val classWriter = ClassWriter( 0) val classWriter = ClassWriter( 0)
var isExported = false
classReader.accept(object : ClassVisitor(API_VERSION, classWriter) { classReader.accept(object : ClassVisitor(API_VERSION, classWriter) {
override fun visit(
version: Int,
access: Int,
name: String?,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
val isPublic = access and ACC_PUBLIC != 0
if (isPublic && usedInternalApiPackages.any { name?.startsWith(it) == true }) {
isExported = true
}
super.visit(version, access, name, signature, superName, interfaces)
}
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor {
if (descriptor == "Ljdk/Exported;") {
isExported = true
}
return super.visitAnnotation(descriptor, visible)
}
}, SKIP_CODE) }, SKIP_CODE)
val result = File(outDir, zipEntry.name)
result.ensureParentDirsCreated() if (isExported) {
result.writeBytes(classWriter.toByteArray()) val result = File(outDir, zipEntry.name)
result.parentFile.mkdirs()
result.writeBytes(classWriter.toByteArray())
}
} }
} }
} }
@@ -54,32 +75,7 @@ val toolsJarStubs by tasks.registering {
val jar = tasks.register<Jar>("jar") { val jar = tasks.register<Jar>("jar") {
dependsOn(toolsJarStubs) dependsOn(toolsJarStubs)
from { from {
fileTree(toolsJarStubs.get().outputs.files.singleFile).matching { fileTree(toolsJarStubs.get().outputs.files.singleFile)
exclude("META-INF/**")
exclude("sun/tools/attach/LinuxAttachProvider.class")
exclude("sun/tools/attach/LinuxVirtualMachine*")
exclude("sun/tools/attach/BsdAttachProvider.class")
exclude("sun/tools/attach/BsdVirtualMachine*")
exclude("sun/tools/attach/WindowsAttachProvider.class")
exclude("sun/tools/attach/WindowsVirtualMachine*")
// Windows only classes
exclude("com/sun/tools/jdi/SharedMemoryAttachingConnector$1.class")
exclude("com/sun/tools/jdi/SharedMemoryAttachingConnector.class")
exclude("com/sun/tools/jdi/SharedMemoryConnection.class")
exclude("com/sun/tools/jdi/SharedMemoryListeningConnector$1.class")
exclude("com/sun/tools/jdi/SharedMemoryListeningConnector.class")
exclude("com/sun/tools/jdi/SharedMemoryTransportService${'$'}SharedMemoryListenKey.class")
exclude("com/sun/tools/jdi/SharedMemoryTransportService.class")
exclude("com/sun/tools/jdi/SharedMemoryTransportServiceCapabilities.class")
exclude("com/sun/tools/jdi/SunSDK.class")
// Deprecated class which has differences in api between versions
exclude("com/sun/tools/javadoc/JavaScriptScanner.class")
}
} }
} }