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.common.toBooleanLenient
|
||||||
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
|
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem
|
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.config.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.index.*
|
import org.jetbrains.kotlin.cli.jvm.index.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
|
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
|
||||||
@@ -171,9 +170,28 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
|
|
||||||
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
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 {
|
jarFileSystem = when {
|
||||||
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM) ||
|
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM) || configuration.getBoolean(CommonConfigurationKeys.USE_FIR) -> {
|
||||||
configuration.getBoolean(CommonConfigurationKeys.USE_FIR) -> FastJarFileSystem()
|
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
|
else -> applicationEnvironment.jarFileSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import java.nio.channels.FileChannel
|
|||||||
|
|
||||||
private typealias RandomAccessFileAndBuffer = Pair<RandomAccessFile, MappedByteBuffer>
|
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> =
|
private val myHandlers: MutableMap<String, FastJarHandler> =
|
||||||
ConcurrentFactoryMap.createMap { key: String -> FastJarHandler(this@FastJarFileSystem, key) }
|
ConcurrentFactoryMap.createMap { key: String -> FastJarHandler(this@FastJarFileSystem, key) }
|
||||||
|
|
||||||
@@ -69,25 +69,27 @@ class FastJarFileSystem : DeprecatedVirtualFileSystem() {
|
|||||||
val pathInJar = path.substring(separator + 2)
|
val pathInJar = path.substring(separator + 2)
|
||||||
return Couple.of(localPath, pathInJar)
|
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.")
|
private val IS_PRIOR_9_JRE = System.getProperty("java.specification.version", "").startsWith("1.")
|
||||||
|
|
||||||
internal fun ByteBuffer.unmapBuffer() {
|
private fun prepareCleanerCallback(): ((ByteBuffer) -> Unit)? {
|
||||||
if (!isDirect) return
|
return try {
|
||||||
|
|
||||||
try {
|
|
||||||
if (IS_PRIOR_9_JRE) {
|
if (IS_PRIOR_9_JRE) {
|
||||||
val cleaner = this::class.java.getMethod("cleaner")
|
val cleaner = Class.forName("java.nio.DirectByteBuffer").getMethod("cleaner")
|
||||||
|
|
||||||
cleaner.isAccessible = true
|
cleaner.isAccessible = true
|
||||||
|
|
||||||
val clean = Class.forName("sun.misc.Cleaner").getMethod("clean")
|
val clean = Class.forName("sun.misc.Cleaner").getMethod("clean")
|
||||||
clean.isAccessible = true
|
clean.isAccessible = true
|
||||||
|
|
||||||
clean.invoke(cleaner.invoke(this))
|
{ buffer: ByteBuffer -> clean.invoke(cleaner.invoke(buffer)) }
|
||||||
} else {
|
} else {
|
||||||
val unsafeClass = try {
|
val unsafeClass = try {
|
||||||
Class.forName("sun.misc.Unsafe")
|
Class.forName("sun.misc.Unsafe")
|
||||||
@@ -103,10 +105,11 @@ internal fun ByteBuffer.unmapBuffer() {
|
|||||||
val theUnsafeField = unsafeClass.getDeclaredField("theUnsafe")
|
val theUnsafeField = unsafeClass.getDeclaredField("theUnsafe")
|
||||||
theUnsafeField.isAccessible = true
|
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) {
|
} 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.VirtualFile
|
||||||
import com.intellij.openapi.vfs.impl.ZipHandler
|
import com.intellij.openapi.vfs.impl.ZipHandler
|
||||||
import com.intellij.util.containers.FactoryMap
|
import com.intellij.util.containers.FactoryMap
|
||||||
import com.intellij.util.io.FileAccessorCache
|
|
||||||
import com.intellij.util.text.ByteArrayCharSequence
|
import com.intellij.util.text.ByteArrayCharSequence
|
||||||
import java.io.File
|
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.RandomAccessFile
|
import java.io.RandomAccessFile
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.MappedByteBuffer
|
|
||||||
import java.nio.channels.FileChannel
|
import java.nio.channels.FileChannel
|
||||||
|
|
||||||
class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandler(path) {
|
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 }
|
ourEntryMap = mappedByteBuffer.parseCentralDirectory().associateBy { it.relativePath }
|
||||||
cachedManifest = ourEntryMap[MANIFEST_PATH]?.let(mappedByteBuffer::contentsToByteArray)
|
cachedManifest = ourEntryMap[MANIFEST_PATH]?.let(mappedByteBuffer::contentsToByteArray)
|
||||||
} finally {
|
} finally {
|
||||||
mappedByteBuffer.unmapBuffer()
|
with(fileSystem) {
|
||||||
|
mappedByteBuffer.unmapBuffer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user