Fallback to CoreJarFileSystem when JDK doesn't support buffers unmapping

This commit is contained in:
Denis.Zharkov
2021-07-20 16:17:30 +03:00
committed by TeamCityServer
parent c6525974d0
commit 3afed7f972
3 changed files with 37 additions and 18 deletions
@@ -69,7 +69,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarHandler
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.index.*
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
@@ -171,9 +170,28 @@ class KotlinCoreEnvironment private constructor(
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
if (configuration.getBoolean(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM)) {
messageCollector?.report(
STRONG_WARNING,
"Using new faster version of JAR FS: it should make your build faster, but the new implementation is experimental"
)
}
jarFileSystem = when {
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM) ||
configuration.getBoolean(CommonConfigurationKeys.USE_FIR) -> FastJarFileSystem()
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM) || configuration.getBoolean(CommonConfigurationKeys.USE_FIR) -> {
val fastJarFs = FastJarFileSystem.createIfUnmappingPossible()
if (fastJarFs == null) {
messageCollector?.report(
STRONG_WARNING,
"Your JDK doesn't seem to support mapped buffer unmapping, so the slower (old) version of JAR FS will be used"
)
applicationEnvironment.jarFileSystem
} else {
fastJarFs
}
}
else -> applicationEnvironment.jarFileSystem
}
@@ -19,7 +19,7 @@ import java.nio.channels.FileChannel
private typealias RandomAccessFileAndBuffer = Pair<RandomAccessFile, MappedByteBuffer>
class FastJarFileSystem : DeprecatedVirtualFileSystem() {
class FastJarFileSystem private constructor(internal val unmapBuffer: MappedByteBuffer.() -> Unit) : DeprecatedVirtualFileSystem() {
private val myHandlers: MutableMap<String, FastJarHandler> =
ConcurrentFactoryMap.createMap { key: String -> FastJarHandler(this@FastJarFileSystem, key) }
@@ -69,25 +69,27 @@ class FastJarFileSystem : DeprecatedVirtualFileSystem() {
val pathInJar = path.substring(separator + 2)
return Couple.of(localPath, pathInJar)
}
fun createIfUnmappingPossible(): FastJarFileSystem? {
val cleanerCallBack = prepareCleanerCallback() ?: return null
return FastJarFileSystem(cleanerCallBack)
}
}
}
private val IS_PRIOR_9_JRE = System.getProperty("java.specification.version", "").startsWith("1.")
internal fun ByteBuffer.unmapBuffer() {
if (!isDirect) return
try {
private fun prepareCleanerCallback(): ((ByteBuffer) -> Unit)? {
return try {
if (IS_PRIOR_9_JRE) {
val cleaner = this::class.java.getMethod("cleaner")
val cleaner = Class.forName("java.nio.DirectByteBuffer").getMethod("cleaner")
cleaner.isAccessible = true
val clean = Class.forName("sun.misc.Cleaner").getMethod("clean")
clean.isAccessible = true
clean.invoke(cleaner.invoke(this))
{ buffer: ByteBuffer -> clean.invoke(cleaner.invoke(buffer)) }
} else {
val unsafeClass = try {
Class.forName("sun.misc.Unsafe")
@@ -103,10 +105,11 @@ internal fun ByteBuffer.unmapBuffer() {
val theUnsafeField = unsafeClass.getDeclaredField("theUnsafe")
theUnsafeField.isAccessible = true
val theUnsafe = theUnsafeField.get(null)
val theUnsafe = theUnsafeField.get(null);
clean.invoke(theUnsafe, this)
{ buffer: ByteBuffer -> clean.invoke(theUnsafe, buffer) }
}
} catch (ex: Exception) {
null
}
}
@@ -8,14 +8,10 @@ import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.util.containers.FactoryMap
import com.intellij.util.io.FileAccessorCache
import com.intellij.util.text.ByteArrayCharSequence
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandler(path) {
@@ -31,7 +27,9 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandl
ourEntryMap = mappedByteBuffer.parseCentralDirectory().associateBy { it.relativePath }
cachedManifest = ourEntryMap[MANIFEST_PATH]?.let(mappedByteBuffer::contentsToByteArray)
} finally {
mappedByteBuffer.unmapBuffer()
with(fileSystem) {
mappedByteBuffer.unmapBuffer()
}
}
}