You might be encountering this problem because you're trying to run JavaFX from Kotlin via command line. As Kotlin uses its own URLClassLoader that isn't populated by the underlying JVM's system classloader as parent, JavaFX classes will not be found when JavaFX is present in the underlying JVM (for example because the JVM is Azul Zulu 18 with JavaFX included) implicitly but not explicitly on the classpath.
The workaround is to create your own URLClassLoader with the same URLs as Kotlin's ClassLoader, using the JVM's system classloader as parent, and then use that via Reflection.
Here's an example of how to do that with an additional main()
method.
import java.net.URLClassLoader
import javafx.application.Application
import javafx.event.*
import javafx.scene.*
import javafx.scene.control.*
import javafx.scene.layout.*
import javafx.stage.*
class Hello : Application() {
override fun start(primaryStage: Stage) {
primaryStage.setTitle("Hello")
val label = Label()
label.setText("Hello, world!")
val root = StackPane()
root.getChildren().add(label)
primaryStage.setScene(Scene(root))
primaryStage.show()
}
companion object {
@JvmStatic
fun main(vararg args: String) {
launch(Hello::class.java, *args)
}
}
}
fun main(vararg args: String) {
class Foo
URLClassLoader((Foo::class.java.getClassLoader() as URLClassLoader).getURLs(), ClassLoader.getSystemClassLoader())
.loadClass("Hello")
.getMethod("main", Array<String>::class.java)
.invoke(null, args)
}
I've tested this with Kotlin 1.7.10 and Azul Zulu 18.0.2.fx on Kubuntu 22.04.