Cleanup after compilation in daemon

This commit is contained in:
Ilya Chernikov
2015-11-17 13:19:23 +01:00
parent 85b487cd84
commit 6867023274
2 changed files with 43 additions and 1 deletions
@@ -287,6 +287,9 @@ public class KotlinCoreEnvironment private constructor(
return KotlinCoreEnvironment(parentDisposable, createApplicationEnvironment(parentDisposable, configuration, extensionConfigs), configuration)
}
// used in the daemon for jar cache cleanup
public val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
private fun getOrCreateApplicationEnvironmentForProduction(configuration: CompilerConfiguration, configFilePaths: List<String>): JavaCoreApplicationEnvironment {
synchronized (APPLICATION_LOCK) {
if (ourApplicationEnvironment != null)
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.rmi.service
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
@@ -166,7 +167,8 @@ class CompileServiceImpl(
override fun releaseCompileSession(sessionId: Int) = ifAlive_Nothing(minAliveness = Aliveness.LastSession) {
synchronized(state.sessions) {
state.sessions.remove(sessionId)
// TODO: some cleanup goes here
log.info("cleaning after session")
clearJarCache()
if (state.sessions.isEmpty()) {
// TODO: and some goes here
}
@@ -473,6 +475,43 @@ class CompileServiceImpl(
}
}
private fun clearJarCache() {
callVoidStaticMethod("com.intellij.openapi.vfs.impl.ZipHandler", "clearFileAccessorCache")
val classloader = javaClass.classLoader
// TODO: replace the following code with direct call to CoreJarFileSystem.<clearCache> as soon as it will be available (hopefully in 15.02)
try {
KotlinCoreEnvironment.applicationEnvironment?.jarFileSystem.let { jarfs ->
val jarfsClass = classloader.loadClass("com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem")
val privateHandlersField = jarfsClass.getDeclaredField("myHandlers")
privateHandlersField.isAccessible = true
privateHandlersField.get(jarfs)?.let {
val clearMethod = privateHandlersField.type.getMethod("clear")
if (clearMethod != null) {
clearMethod.invoke(it)
log.info("successfully cleared com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.myHandlers")
}
else {
log.info("unable to access com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.myHandlers.clear")
}
} ?: log.info("unable to access CoreJarFileSystem.myHandlers (${privateHandlersField.get(jarfs)})")
}
}
catch (e: Exception) {
log.log(Level.SEVERE, "error clearing CoreJarFileSystem", e)
}
}
// copied (with edit) from gradle plugin
private fun callVoidStaticMethod(classFqName: String, methodName: String) {
// compiler classloader == current classloader for now
// TODO: consider abstracting classloader, for easier changing it for a compiler
val cls = this.javaClass.classLoader.loadClass(classFqName)
val method = cls.getMethod(methodName)
method.invoke(null)
}
private fun<R> ifAlive(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> R): CompileService.CallResult<R> = rwlock.read {
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged) { CompileService.CallResult.Good(body()) }
}