Fallback to CoreJarFileSystem when JDK doesn't support buffers unmapping
This commit is contained in:
committed by
TeamCityServer
parent
c6525974d0
commit
3afed7f972
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user