diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/ExitCode.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/ExitCode.java
index e8c2a283040..1f70b5521cd 100644
--- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/ExitCode.java
+++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/ExitCode.java
@@ -20,7 +20,9 @@ public enum ExitCode {
OK(0),
COMPILATION_ERROR(1),
INTERNAL_ERROR(2),
- SCRIPT_EXECUTION_ERROR(3);
+ SCRIPT_EXECUTION_ERROR(3),
+ OOM_ERROR(137), // 137 is commonly used to indicate OOM error
+ ;
private final int code;
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt
index 6272347ab90..365c77a53ee 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt
@@ -20,8 +20,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.analyzer.CompilationErrorException
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY
-import org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR
-import org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR
+import org.jetbrains.kotlin.cli.common.ExitCode.*
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
import org.jetbrains.kotlin.cli.common.messages.*
@@ -122,7 +121,7 @@ abstract class CLICompiler : CLITool() {
return COMPILATION_ERROR
} catch (t: Throwable) {
MessageCollectorUtil.reportException(collector, t)
- return INTERNAL_ERROR
+ return if (t is OutOfMemoryError) OOM_ERROR else INTERNAL_ERROR
} finally {
collector.flush()
}
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt
index f155061ceda..1291a0bc49e 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt
@@ -100,6 +100,25 @@ class KotlinDaemonIT : KGPDaemonsBaseTest() {
}
}
+ @DisplayName("On Kotlin daemon OOM helpful message is displayed")
+ @GradleTest
+ fun displaySpecialMessageOnOOM(gradleVersion: GradleVersion) {
+ project(
+ "kotlinProject",
+ gradleVersion,
+ buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.INFO)
+ ) {
+ gradleProperties.append(
+ "\nkotlin.daemon.jvmargs=-Xmx16m"
+ )
+
+ buildAndFail("assemble") {
+ assertOutputContains("Not enough memory to run compilation. Try to increase it via 'gradle.properties':")
+ assertOutputContains("kotlin.daemon.jvmargs=-Xmx")
+ }
+ }
+ }
+
private fun BuildResult.assertGradleClasspathNotLeaked() {
assertOutputContains("Kotlin compiler classpath:")
val daemonClasspath = output
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt
index 63dcc3dfe06..5c826382459 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt
@@ -127,12 +127,12 @@ internal class GradleKotlinCompilerWork @Inject constructor(
override fun run() {
try {
val messageCollector = GradlePrintingMessageCollector(log, allWarningsAsErrors)
- val exitCode = compileWithDaemonOrFallbackImpl(messageCollector)
+ val (exitCode, executionStrategy) = compileWithDaemonOrFallbackImpl(messageCollector)
if (incrementalCompilationEnvironment?.disableMultiModuleIC == true) {
incrementalCompilationEnvironment.multiModuleICSettings.buildHistoryFile.delete()
}
- throwGradleExceptionIfError(exitCode)
+ throwGradleExceptionIfError(exitCode, executionStrategy)
} finally {
val properties = ArrayList()
COMPILE_INCREMENTAL_WITH_CLASSPATH_SNAPSHOTS.value.toBooleanLenient()?.let {
@@ -151,7 +151,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
}
}
- private fun compileWithDaemonOrFallbackImpl(messageCollector: MessageCollector): ExitCode {
+ private fun compileWithDaemonOrFallbackImpl(messageCollector: MessageCollector): Pair {
with(log) {
kotlinDebug { "Kotlin compiler class: ${compilerClassName}" }
kotlinDebug { "Kotlin compiler classpath: ${compilerFullClasspath.joinToString { it.canonicalPath }}" }
@@ -162,7 +162,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val daemonExitCode = compileWithDaemon(messageCollector)
if (daemonExitCode != null) {
- return daemonExitCode
+ return daemonExitCode to KotlinCompilerExecutionStrategy.DAEMON
} else {
log.warn("Could not connect to kotlin daemon. Using fallback strategy.")
}
@@ -170,9 +170,9 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val isGradleDaemonUsed = System.getProperty("org.gradle.daemon")?.let(String::toBoolean)
return if (compilerExecutionStrategy == KotlinCompilerExecutionStrategy.IN_PROCESS || isGradleDaemonUsed == false) {
- compileInProcess(messageCollector)
+ compileInProcess(messageCollector) to KotlinCompilerExecutionStrategy.IN_PROCESS
} else {
- compileOutOfProcess()
+ compileOutOfProcess() to KotlinCompilerExecutionStrategy.OUT_OF_PROCESS
}
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt
index cce4fd6ed50..ed41eb91e53 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt
@@ -132,7 +132,7 @@ abstract class KotlinJsDce : AbstractKotlinCompileTool(), Kotl
buildDir,
jvmArgs
)
- throwGradleExceptionIfError(exitCode)
+ throwGradleExceptionIfError(exitCode, KotlinCompilerExecutionStrategy.OUT_OF_PROCESS)
}
private fun isDceCandidate(file: File): Boolean {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/tasksUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/tasksUtils.kt
index d202141f6e3..c80b73cd459 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/tasksUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/tasksUtils.kt
@@ -14,13 +14,26 @@ import org.jetbrains.kotlin.incremental.cleanDirectoryContents
import org.jetbrains.kotlin.incremental.forceDeleteRecursively
import java.io.File
-fun throwGradleExceptionIfError(exitCode: ExitCode) {
+fun throwGradleExceptionIfError(
+ exitCode: ExitCode,
+ executionStrategy: KotlinCompilerExecutionStrategy
+) {
when (exitCode) {
ExitCode.COMPILATION_ERROR -> throw GradleException("Compilation error. See log for more details")
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details")
ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException("Script execution error. See log for more details")
- ExitCode.OK -> {
+ ExitCode.OOM_ERROR -> {
+ var exceptionMessage = "Not enough memory to run compilation."
+ when (executionStrategy) {
+ KotlinCompilerExecutionStrategy.DAEMON ->
+ exceptionMessage += " Try to increase it via 'gradle.properties':\nkotlin.daemon.jvmargs=-Xmx"
+ KotlinCompilerExecutionStrategy.IN_PROCESS ->
+ exceptionMessage += " Try to increase it via 'gradle.properties':\norg.gradle.jvmargs=-Xmx"
+ KotlinCompilerExecutionStrategy.OUT_OF_PROCESS -> Unit
+ }
+ throw GradleException(exceptionMessage)
}
+ ExitCode.OK -> Unit
else -> throw IllegalStateException("Unexpected exit code: $exitCode")
}
}