Skip to content

Build project using JDK 11 #1733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ to Gradle (in Preferences -> Build, Execution, Deployment -> Build Tools -> Grad

### Requirements

* JDK >= 1.8 referred to by the `JAVA_HOME` environment variable. JDK must include JavaFX.
* JDK >= 11 referred to by the `JAVA_HOME` environment variable.
* JDK 1.6 referred to by the `JDK_16` environment variable. It is okay to have `JDK_16` pointing to `JAVA_HOME` for external contributions.
* JDK 1.8 referred to by the `JDK_18` environment variable. Only used by nightly stress-tests. It is okay to have `JDK_16` pointing to `JAVA_HOME` for external contributions.

## Contributions and releases

Expand Down
23 changes: 21 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import org.jetbrains.kotlin.konan.target.HostManager

Expand Down Expand Up @@ -68,6 +68,7 @@ buildscript {
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version"
classpath "org.openjfx:javafx-plugin:$javafx_plugin_version"
classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version"

// JMH plugins
Expand Down Expand Up @@ -261,8 +262,26 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) {
// Report Kotlin compiler version when building project
println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION")

// --------------- Publish only from under JDK11+ ---------------
task checkJdkForPublish {
doFirst {
String javaVersion = System.properties["java.version"]
int i = javaVersion.indexOf('.')
int javaVersionMajor = (i < 0 ? javaVersion : javaVersion.substring(0, i)).toInteger()
if (javaVersionMajor < 11) {
throw new GradleException("Project can be build for publishing only under JDK 11+, but found ${javaVersion}")
}
}
}

// --------------- Configure sub-projects that are published ---------------
task deploy(dependsOn: getTasksByName("publish", true) + getTasksByName("publishNpm", true))
def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm", true)

publishTasks.each {
it.dependsOn checkJdkForPublish
}

task deploy(dependsOn: publishTasks)

apply plugin: 'base'

Expand Down
10 changes: 9 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
#

# Kotlin
Expand All @@ -17,8 +17,16 @@ byte_buddy_version=1.9.3
reactor_vesion=3.2.5.RELEASE
reactive_streams_version=1.0.2
rxjava2_version=2.2.8
javafx_version=11.0.2
javafx_plugin_version=0.0.8
binary_compatibility_validator_version=0.1.1

# Android versions
android_version=4.1.1.4
android_support_version=26.1.0
robolectric_version=4.0.2
baksmali_version=2.2.7

# JS
gradle_node_version=1.2.0
node_version=8.9.3
Expand Down
8 changes: 4 additions & 4 deletions kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.debug

Expand All @@ -20,7 +20,7 @@ class RunningThreadStackMergeTest : DebugTestBase() {
verifyDump(
"Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@50284dc4, state: RUNNING\n" +
"\tat sun.misc.Unsafe.park(Native Method)\n" +
"\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
"\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
"\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
"\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
Expand Down Expand Up @@ -75,7 +75,7 @@ class RunningThreadStackMergeTest : DebugTestBase() {
verifyDump(
"Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@3aea3c67, state: RUNNING\n" +
"\tat sun.misc.Unsafe.park(Native Method)\n" +
"\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
"\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
"\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
"\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
Expand Down Expand Up @@ -116,7 +116,7 @@ class RunningThreadStackMergeTest : DebugTestBase() {
verifyDump(
"Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@3aea3c67, state: RUNNING\n" +
"\tat sun.misc.Unsafe.park(Native Method)\n" +
"\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
"\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
"\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
"\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
Expand Down
18 changes: 8 additions & 10 deletions kotlinx-coroutines-debug/test/StracktraceUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.coroutines.debug
Expand All @@ -11,6 +11,8 @@ public fun String.trimStackTrace(): String =
trimIndent()
.replace(Regex(":[0-9]+"), "")
.replace(Regex("#[0-9]+"), "")
.replace(Regex("(?<=\tat )[^\n]*/"), "")
.replace(Regex("\t"), "")
.applyBackspace()

public fun String.applyBackspace(): String {
Expand All @@ -30,16 +32,12 @@ public fun String.applyBackspace(): String {

public fun verifyStackTrace(e: Throwable, traces: List<String>) {
val stacktrace = toStackTrace(e)
val trimmedStackTrace = stacktrace.trimStackTrace()
traces.forEach {
val expectedLines = it.trimStackTrace().split("\n")
for (i in 0 until expectedLines.size) {
traces.forEach {
assertTrue(
stacktrace.trimStackTrace().contains(it.trimStackTrace()),
"\nExpected trace element:\n$it\n\nActual stacktrace:\n$stacktrace"
)
}
}
assertTrue(
trimmedStackTrace.contains(it.trimStackTrace()),
"\nExpected trace element:\n$it\n\nActual stacktrace:\n$stacktrace"
)
}

val causes = stacktrace.count("Caused by")
Expand Down
9 changes: 4 additions & 5 deletions ui/kotlinx-coroutines-android/android-unit-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

repositories {
google()
}

dependencies {
testImplementation 'com.google.android:android:4.1.1.4'
testImplementation 'com.android.support:support-annotations:26.1.0'
testImplementation 'com.google.android:android:4.1.1.4'
testImplementation 'org.robolectric:robolectric:4.0-alpha-3'
testImplementation "com.google.android:android:$android_version"
testImplementation "com.android.support:support-annotations:$android_support_version"
testImplementation "org.robolectric:robolectric:$robolectric_version"
testImplementation project(":kotlinx-coroutines-test")
testImplementation project(":kotlinx-coroutines-android")
}
12 changes: 6 additions & 6 deletions ui/kotlinx-coroutines-android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

repositories {
Expand All @@ -18,12 +18,12 @@ configurations {
}

dependencies {
compileOnly 'com.google.android:android:4.1.1.4'
compileOnly 'com.android.support:support-annotations:26.1.0'
compileOnly "com.google.android:android:$android_version"
compileOnly "com.android.support:support-annotations:$android_support_version"

testImplementation 'com.google.android:android:4.1.1.4'
testImplementation 'org.robolectric:robolectric:4.0-alpha-3'
testImplementation 'org.smali:baksmali:2.2.7'
testImplementation "com.google.android:android:$android_version"
testImplementation "org.robolectric:robolectric:$robolectric_version"
testImplementation "org.smali:baksmali:$baksmali_version"

// TODO Replace with a 1.6.x version once released to maven.google.com.
r8 'com.android.tools:r8:a7ce65837bec81c62261bf0adac73d9c09d32af2'
Expand Down
39 changes: 38 additions & 1 deletion ui/kotlinx-coroutines-javafx/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

static int javaVersionMajor() {
String javaVersion = System.properties["java.version"]
int i = javaVersion.indexOf('.')
return (i < 0 ? javaVersion : javaVersion.substring(0, i)).toInteger()
}

// JDK11+ does not bundle JavaFx and the plugin for JavaFx support is compiled with class file version 55.0 (JDK 11)
if (javaVersionMajor() >= 11) {
apply plugin: 'org.openjfx.javafxplugin'

javafx {
version = javafx_version
modules = ['javafx.controls']
configuration = 'compile'
}
}

task checkJdk8() {
// only fail w/o JDK_18 when actually trying to test, not during project setup phase
doLast {
if (!System.env.JDK_18) {
throw new GradleException("JDK_18 environment variable is not defined. " +
"Can't run JDK 8 compatibility tests. " +
"Please ensure JDK 8 is installed and that JDK_18 points to it.")
}
}
}

task jdk8Test(type: Test, dependsOn: [compileTestKotlin, checkJdk8]) {
classpath = files { test.classpath }
testClassesDirs = files { test.testClassesDirs }
executable = "$System.env.JDK_18/bin/java"
}

// Run these tests only during nightly stress test
jdk8Test.onlyIf { project.properties['stressTest'] != null }
build.dependsOn jdk8Test
52 changes: 27 additions & 25 deletions ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import javafx.util.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.javafx.JavaFx.delay
import java.lang.UnsupportedOperationException
import java.lang.reflect.*
import java.util.concurrent.*
import kotlin.coroutines.*
Expand Down Expand Up @@ -115,41 +116,42 @@ private class PulseTimer : AnimationTimer() {
}
}

/** @return [true] if initialized successfully, and [false] if no display is detected */
internal fun initPlatform(): Boolean = PlatformInitializer.success

// Lazily try to initialize JavaFx platform just once
private object PlatformInitializer {
val success = run {
/*
* Try to instantiate JavaFx platform in a way which works
* both on Java 8 and Java 11 and does not produce "illegal reflective access":
*
* 1) Try to invoke javafx.application.Platform.startup if this class is
* present in a classpath.
* 2) If it is not successful and does not because it is already started,
* fallback to PlatformImpl.
*
* Ignore exception anyway in case of unexpected changes in API, in that case
* user will have to instantiate it manually.
* both on Java 8 and Java 11 and does not produce "illegal reflective access".
*/
val runnable = Runnable {}
runCatching {
// Invoke public API if it is present
Class.forName("javafx.application.Platform")
.getMethod("startup", java.lang.Runnable::class.java)
.invoke(null, runnable)
}.recoverCatching { exception ->
// Recover -> check re-initialization
val cause = exception.cause
if (exception is InvocationTargetException && cause is IllegalStateException
&& "Toolkit already initialized" == cause.message) {
// Toolkit is already initialized -> success, return
Unit
} else { // Fallback to Java 8 API
Class.forName("com.sun.javafx.application.PlatformImpl")
try {
val runnable = Runnable {}
// Invoke the public API if it is present.
runCatching {
Class.forName("javafx.application.Platform")
.getMethod("startup", java.lang.Runnable::class.java)
}.map { method ->
method.invoke(null, runnable)
return@run true
}
// If we are here, it means the public API is not present. Try the private API.
Class.forName("com.sun.javafx.application.PlatformImpl")
.getMethod("startup", java.lang.Runnable::class.java)
.invoke(null, runnable)
true
} catch (exception: InvocationTargetException) {
// Can only happen as a result of [Method.invoke].
val cause = exception.cause!!
when {
// Maybe the problem is that JavaFX is already initialized? Everything is good then.
cause is IllegalStateException && "Toolkit already initialized" == cause.message -> true
// If the problem is the headless environment, it is okay.
cause is UnsupportedOperationException && "Unable to open DISPLAY" == cause.message -> false
// Otherwise, the exception demonstrates an anomaly.
else -> throw cause
}
}.isSuccess
}
}
}
4 changes: 2 additions & 2 deletions ui/kotlinx-coroutines-swing/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

dependencies {
testCompile project(':kotlinx-coroutines-jdk8')
}
}
5 changes: 2 additions & 3 deletions ui/kotlinx-coroutines-swing/test/SwingTest.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.coroutines.swing

import javafx.application.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
Expand Down Expand Up @@ -81,7 +80,7 @@ class SwingTest : TestBase() {
join(component)
}

private suspend fun join(component: SwingTest.SwingComponent) {
private suspend fun join(component: SwingComponent) {
component.coroutineContext[Job]!!.join()
}

Expand Down