Skip to content

Commit 15407e3

Browse files
authored
Try to reflectively use public JavaFX API before PlatormImpl fallback… (Kotlin#798)
Try to reflectively use public JavaFX API before PlatormImpl fallback, ignore "Toolkit already initialized" * Fixes "illegal reflective access" warning on Java 9 * Works on all versions of Java * Avoid conflicts with multiple calls to Platform.startup Fixes Kotlin#463
1 parent 49b6305 commit 15407e3

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import javafx.event.*
1010
import javafx.util.*
1111
import kotlinx.coroutines.*
1212
import kotlinx.coroutines.internal.*
13+
import java.lang.IllegalStateException
14+
import java.lang.reflect.*
1315
import java.util.concurrent.*
1416
import kotlin.coroutines.*
1517

@@ -114,9 +116,30 @@ private class PulseTimer : AnimationTimer() {
114116
}
115117

116118
internal fun initPlatform() {
117-
// Ad-hoc workaround for #443. Will be fixed with multi-release jar.
118-
// If this code throws an exception (Java 9 + prohibited reflective access), initialize JavaFX directly
119-
Class.forName("com.sun.javafx.application.PlatformImpl")
120-
.getMethod("startup", java.lang.Runnable::class.java)
121-
.invoke(null, java.lang.Runnable { })
119+
/*
120+
* Try to instantiate JavaFx platform in a way which works
121+
* both on Java 8 and Java 11 and does not produce "illegal reflective access":
122+
*
123+
* 1) Try to invoke javafx.application.Platform.startup if this class is
124+
* present in a classpath (since Java 9 it is a separate dependency)
125+
* 2) If it is not present, invoke plain old PlatformImpl.startup
126+
*
127+
* Additionally, ignore ISE("Toolkit already initialized") because since Java 9
128+
* consecutive calls to 'startup' throw it
129+
*/
130+
val platformClass = runCatching {
131+
Class.forName("javafx.application.Platform") // Java 9+
132+
}.getOrElse {
133+
Class.forName("com.sun.javafx.application.PlatformImpl") // Fallback
134+
}
135+
136+
try {
137+
platformClass.getMethod("startup", java.lang.Runnable::class.java)
138+
.invoke(null, java.lang.Runnable { })
139+
} catch (e: InvocationTargetException) {
140+
val cause = e.cause
141+
if (cause !is IllegalStateException || "Toolkit already initialized" != cause.message) {
142+
throw e
143+
}
144+
}
122145
}

ui/kotlinx-coroutines-javafx/test/JavaFxTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.junit.*
1111
class JavaFxTest : TestBase() {
1212
@Before
1313
fun setup() {
14-
ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-")
14+
ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-", "InvokeLaterDispatcher")
1515
}
1616

1717
@Test

0 commit comments

Comments
 (0)