如何在GraalVM多语言上下文的JS中访问Kotlin数据类字段
解决GraalVM JS上下文访问Kotlin数据类属性的问题
问题根源在于Kotlin的val属性默认编译为private字段+public getter方法(比如name对应getName()),而GraalVM默认仅允许直接访问Java的public字段,不会自动将getter方法映射为属性访问。以下是两种解决方案:
方案一:用@JvmField注解将属性转为Java public字段
给Kotlin数据类的属性添加@JvmField注解,强制编译器将其编译为Java的public字段,这样GraalVM JS就能直接通过.name访问:
import kotlin.jvm.JvmField import org.graalvm.polyglot.Context import org.graalvm.polyglot.HostAccess data class ExampleState( @JvmField val name: String = "Hello world" ) fun main() { Context.newBuilder("js") .allowHostAccess(HostAccess.ALL) .out(System.out) .err(System.err) .build() .use { context -> val bindings = context.getBindings("js") bindings.putMember("state", ExampleState()) println(context.eval("js", "state.getName()")) // 仍可正常调用 println(context.eval("js", "state.name")) // 现在输出"Hello world" } }
方案二:配置GraalVM HostAccess自动映射getter为属性
无需修改数据类,通过自定义HostAccess配置,让GraalVM自动将JavaBean风格的getter方法映射为属性访问:
import org.graalvm.polyglot.Context import org.graalvm.polyglot.HostAccess data class ExampleState( val name: String = "Hello world" ) fun main() { Context.newBuilder("js") .allowHostAccess(HostAccess.newBuilder() .allowPublicAccess(true) .allowGetters(true) // 启用getter到属性的自动映射 .allowSetters(true) // 若需要访问setter也可添加 .build()) .out(System.out) .err(System.err) .build() .use { context -> val bindings = context.getBindings("js") bindings.putMember("state", ExampleState()) println(context.eval("js", "state.name")) // 输出"Hello world" } }
两种方案的区别:
- 方案一直接修改了属性的Java编译形态,适用于需要和Java代码直接交互的场景;
- 方案二通过GraalVM配置实现映射,无需修改数据类,更适合纯Kotlin+GraalVM的场景。
内容的提问来源于stack exchange,提问作者d0x
相关产品推荐
相关产品推荐

