Kotlin在运行时从源代码动态编译一个类

时间:2018-03-21 20:54:05

标签: kotlin

是否可以在运行时编译和实例化Kotlin类?我正在谈论类似的东西但是使用Kotlin API:How do I programmatically compile and instantiate a Java class?

例如: 我将完整的类定义作为String:

val example = "package example\n" +
        "\n" +
        "fun main(args: Array<String>) {\n" +
        "    println(\"Hello World\")\n" +
        "}\n"

然后将其插入某个class.kt并运行它,以便我得到#34; Hello World&#34;在运行时打印在控制台中。

2 个答案:

答案 0 :(得分:1)

您可能需要查看Kotlin脚本,请参阅https://github.com/andrewoma/kotlin-script

或者,您需要编写自己的eval(kotlin-code-string-here)方法,将文本转储到blah.kt文件中,例如,使用外部Kotlin编译器将其编译为blah.class然后动态加载这些类使用Java Classloader进入运行时,执行如下操作:

MainClass.class.classLoader.loadClass("com.mypackage.MyClass")

这可能非常缓慢且不可靠。

另一个不太好的选择是使用Rhino并在Kotlin代码中运行JavaScript。所以再次,你将有一个eval(kotlin-code-string-here)方法将内容转储到blah.kt文件,然后你将使用Kotlin2JS编译器将其编译为JavaScript并使用Rhino直接在Kotlin中执行JavaScript这也不是很好。

另一种选择是使用Kotlin Scripting或外部Kotlin编译器(在两种情况下,Kotlin编译器都必须启动)并且做这样的事情也将允许你动态执行,尽管只在Unix系统上

Runtime.getRuntime().exec("""  "kotlin code here" > blah.kts | sh""")

我不知道有一个干净的解决方案,Kotlin的设计不像PHP / JavaScript / Python那样只是动态地解释文本,它必须先编译成字节码才能在JVM上做任何事情;因此,在每个场景中,您将需要首先以某种方式编译该代码,无论是字节码还是javascript,并且在两种情况下都使用Java Classloader或Rhino将其加载到您的应用程序中。

答案 1 :(得分:0)

请检查this solution的依赖关系,jar资源等。下面的代码不足以成功执行。

但是,要编译动态类,您可以执行以下操作:

val classLoader = Thread.currentThread().contextClassLoader

val engineManager = ScriptEngineManager(classLoader)

setIdeaIoUseFallback() // hack to have ability to do this from IntelliJ Idea context

val ktsEngine: ScriptEngine = engineManager.getEngineByExtension("kts")

ktsEngine.eval("object MyClass { val number = 123 } ")

println(ktsEngine.eval("MyClass.number"))

请注意:此处可以进行代码注入。请小心,并为此使用专用的进程或专用的ClassLoader。

相关问题