实现细节

与其他使用 Truffle 实现的语言一样,Espresso 可以作为原生可执行文件或在 HotSpot 上运行(目前仅在 Linux 上支持)。在第一种情况下,当 Espresso 运行时被编译成原生可执行文件时,它不需要 HotSpot 来运行 Java。但是,它需要一个标准的 Java 核心库(Java 8 的 rt.jar 库或 Java 11+ 的 lib/modules 文件,以及相关的原生库:libjavalibnio 等等)。

Espresso 是一个最小化的 Java VM,它实现了 VM 的所有核心组件,包括:

  • 字节码解释器
  • 字节码验证器
  • 单个 Java 类文件解析器
  • 简单的对象模型
  • Java 本地接口 (JNI) 的 Java 实现
  • Java 中的虚拟机实现
  • Java 调试线协议 (JDWP)

Espresso 重新使用 GraalVM 中的所有 JAR 文件和原生库。所有原生库和方法都通过 Truffle 本地函数接口 (JNI) 加载/访问/调用。JNI 句柄在 Espresso 中实现,例如,所有 Truffle NFI 方法只接收和返回基本类型。为了性能,一些方法被替换,例如,Math.sqrtSystem.arraycopy,避免了昂贵的原生转换。

一些原生库可能包含静态数据,如果从多个 Espresso 上下文甚至从 Espresso 和 HotSpot 上运行的 Java 中使用,这些静态数据会发生冲突。在 Linux 上,Espresso 使用 Truffle NFI 的功能来尝试在隔离的命名空间 (dlmopen) 中加载库。这只有在使用 glibc 的 Linux 上才能使用,并且有很多限制。在运行原生可执行文件时,此模式不会被使用,因为不会与 HotSpot 发生冲突。

当前限制 #

  • Espresso 未实现 JVM 工具接口 (JVMTI)。因此,它不支持 -agentlib-agentpath VM 选项。
  • Espresso 未实现 java.lang.instrument 接口。因此,它不支持 -javaagent VM 选项。
  • Espresso 目前使用 Java 核心库中的标准原生库。这需要允许多语言 Context 进行原生访问。由于这些库的加载方式(通过 Truffle 本地函数接口 (JNI)),因此在 HotSpot 上运行只在 Linux(使用 glibc)上有效。作为原生可执行文件的一部分运行在 Linux、Windows 和 macOS 上有效,但目前仅限于一个上下文。
  • Java 管理扩展 (JMX) 的支持是部分的,一些方法可能返回部分数据。
  • 调试器协议实现 (JDWP) 与 HotSpot 相比,缺少一些功能。它将正确报告支持的 功能。特别是需要枚举所有 Java 对象的操作不受支持。但是,它确实支持 HotSpot 不支持的几个热重载情况。
  • java.MultiThreaded 选项设置为“false”时,引用处理 将不会发生。根据应用程序的不同,这可能会导致资源泄漏。请注意,如果 Espresso 在启用单线程语言的上下文中运行(例如,JavaScript),则此选项会自动设置为“false”。
  • Espresso 还不支持 多语言 API。但是,它提供了访客 Java 多语言 API,如 polyglot.jar 中所述。有关详细信息,请参阅 与 Truffle 语言的互操作性

联系我们