@@ -10,7 +10,7 @@ import javafx.event.*
1010import javafx.util.*
1111import kotlinx.coroutines.*
1212import kotlinx.coroutines.internal.*
13- import java.lang.IllegalStateException
13+ import kotlinx.coroutines.javafx.JavaFx.delay
1414import java.lang.reflect.*
1515import java.util.concurrent.*
1616import kotlin.coroutines.*
@@ -115,31 +115,36 @@ private class PulseTimer : AnimationTimer() {
115115 }
116116}
117117
118- internal fun initPlatform () {
118+ internal fun initPlatform (): Boolean {
119119 /*
120120 * Try to instantiate JavaFx platform in a way which works
121121 * both on Java 8 and Java 11 and does not produce "illegal reflective access":
122122 *
123123 * 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
124+ * present in a classpath.
125+ * 2) If it is not successful and does not because it is already started,
126+ * fallback to PlatformImpl.
126127 *
127- * Additionally, ignore ISE("Toolkit already initialized") because since Java 9
128- * consecutive calls to 'startup' throw it
128+ * Ignore exception anyway in case of unexpected changes in API, in that case
129+ * user will have to instantiate it manually.
129130 */
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
131+ val runnable = Runnable {}
132+ return runCatching {
133+ // Invoke public API if it is present
134+ Class .forName(" javafx.application.Platform" )
135+ .getMethod(" startup" , java.lang.Runnable ::class .java)
136+ .invoke(null , runnable)
137+ }.recoverCatching { exception ->
138+ // Recover -> check re-initialization
139+ val cause = exception.cause
140+ if (exception is InvocationTargetException && cause is IllegalStateException
141+ && " Toolkit already initialized" == cause.message) {
142+ // Toolkit is already initialized -> success, return
143+ Unit
144+ } else { // Fallback to Java 8 API
145+ Class .forName(" com.sun.javafx.application.PlatformImpl" )
146+ .getMethod(" startup" , java.lang.Runnable ::class .java)
147+ .invoke(null , runnable)
143148 }
144- }
149+ }.isSuccess
145150}
0 commit comments