@@ -10,7 +10,7 @@ import javafx.event.*
10
10
import javafx.util.*
11
11
import kotlinx.coroutines.*
12
12
import kotlinx.coroutines.internal.*
13
- import java.lang.IllegalStateException
13
+ import kotlinx.coroutines.javafx.JavaFx.delay
14
14
import java.lang.reflect.*
15
15
import java.util.concurrent.*
16
16
import kotlin.coroutines.*
@@ -115,31 +115,36 @@ private class PulseTimer : AnimationTimer() {
115
115
}
116
116
}
117
117
118
- internal fun initPlatform () {
118
+ internal fun initPlatform (): Boolean {
119
119
/*
120
120
* Try to instantiate JavaFx platform in a way which works
121
121
* both on Java 8 and Java 11 and does not produce "illegal reflective access":
122
122
*
123
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
124
+ * present in a classpath.
125
+ * 2) If it is not successful and does not because it is already started,
126
+ * fallback to PlatformImpl.
126
127
*
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.
129
130
*/
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)
143
148
}
144
- }
149
+ }.isSuccess
145
150
}
0 commit comments