- 适用于 JDK 24 的 GraalVM(最新)
- 适用于 JDK 25 的 GraalVM(早期访问)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发构建
- Truffle 语言实现框架
- Truffle 分支插桩
- 动态对象模型
- 静态对象模型
- 解释器代码的主机优化
- Truffle 函数内联方法
- 分析 Truffle 解释器
- Truffle 互操作 2.0
- 语言实现
- 使用 Truffle 实现新语言
- Truffle 语言和工具迁移到 Java 模块
- Truffle 原生函数接口
- 优化 Truffle 解释器
- 选项
- 栈上替换
- Truffle 字符串指南
- 特化直方图
- 测试 DSL 特化
- 基于多语言 API 的 TCK
- Truffle 编译队列方法
- Truffle 库指南
- Truffle AOT 概述
- Truffle AOT 编译
- 辅助引擎缓存
- Truffle 语言安全点教程
- 单态化
- 拆分算法
- 单态化用例
- 向运行时报告多态特化
上下文退出
不同的 Truffle(客体)语言可能使用不同的退出机制。这并非最佳,因为 Truffle 语言无法检测和处理由其他语言触发的退出。
自 22.0 版起,Truffle 支持客体语言通过使用 TruffleContext.closeExited(Node,int) 触发多语言上下文的硬性显式退出。它为语言提供了一种统一的方式来触发底层多语言上下文的退出。当触发时,所有已初始化的客体语言首先通过 TruffleLanguage.exitContext(C,ExitMode,int) 收到通知,然后所有上下文线程被停止,最后,上下文被关闭。硬性显式退出简称为“硬退出”。
硬退出只是 Truffle 中三种退出类型之一。退出类型如下:
- 上面介绍的新硬退出
- 硬退出通知在执行时,
TruffleLanguage.exitContext(C,ExitMode,int)
的第二个参数使用ExitMode.HARD
。
- 硬退出通知在执行时,
- 隐式“自然退出”
- 在正常上下文关闭期间发生。
- 新引入的退出通知也适用于自然退出,但线程在自然退出通知后不会被强制停止,因此仍在运行的上下文线程可能会阻塞自然退出。
- 自然退出通知在执行时,
TruffleLanguage.exitContext(C,ExitMode,int)
的第二个参数使用ExitMode.NATURAL
。
- “软退出”
- 通过抛出异常类型为
ExceptionType.EXIT
的 Truffle 异常来触发显式退出。 - 该异常不会由 Truffle 自动在其他线程中抛出,它也不会自行触发退出通知或上下文关闭。
- 软退出后上下文仍可完全使用,软退出之后可以接着是自然退出或硬退出。
- 通过抛出异常类型为
为完整起见,多语言上下文也可以通过使用 Context.close(true)
、TruffleContext.closeCancelled(Node,String)
或 TruffleContext.closeResourceExhausted(Node,String)
来取消它并关闭。取消操作会导致所有上下文线程立即停止并关闭上下文,而不会发送任何退出通知。
软退出 #
软退出是通过抛出异常类型为 ExceptionType.EXIT
的 Truffle 异常(即软退出异常)来触发的。该异常不会由 Truffle 自动在其他线程中抛出,也不会自行触发退出通知或上下文关闭。如果未被语言捕获,软退出异常最终会导致嵌入器线程向主机抛出一个 PolyglotException
,其中 PolyglotException.isExit() == true
,且 PolyglotException.getExitStatus()
等于软退出异常指定的值。
软退出后上下文仍可完全使用,但当嵌入器看到 PolyglotException
且 PolyglotException.isExit() == true
时,应关闭上下文,在这种情况下,软退出之后是自然退出。
自然退出 #
自然退出发生在由 Context.close()
或 TruffleContext.close()
触发的正常上下文关闭期间。上图中所示的自然退出包含以下步骤:
-
自然退出由
Context.close()
或TruffleContext.close()
触发。 - 执行所有已初始化语言的退出通知 -
TruffleLanguage.exitContext(C,ExitMode,int)
,其中ExitMode.NATURAL
用作ExitMode
参数。- 客体代码在退出通知期间正常运行。
- 所有已初始化语言都被终结。
- 为所有已初始化的语言调用
TruffleLanguage.finalizeContext(C)
。 - 客体代码在终结期间正常运行。
- 为所有已初始化的语言调用
- 所有语言都被处置。
- 为所有语言调用
TruffleLanguage.disposeContext(C)
。
- 为所有语言调用
硬退出 #
本节详细描述了硬退出过程。多语言上下文的硬退出可以通过 Context.Builder.useSystemExit(boolean)
进行自定义。因此,以下描述分为两个小节。一节说明系统退出未启用(Context.Builder.useSystemExit(false)
- 默认)的情况,另一节说明系统退出已启用(Context.Builder#useSystemExit(true)
)的情况。退出过程的示意图显示在上方图表中。该图还说明了退出过程与上下文取消过程之间的关系。某些框的红色表示上下文在该点无效,并且无法运行任何客体代码。更确切地说,第一个 Truffle 安全点将根据是硬退出还是取消操作正在进行中,抛出一个特殊的 ThreadDeath
退出异常或一个特殊的 ThreadDeath
取消异常。
如果 useSystemExit 被禁用时的行为(默认) #
- 执行所有已初始化语言的退出通知 - TruffleLanguage.exitContext(C,ExitMode,int),其中
ExitMode.HARD
用作ExitMode
参数。- 客体代码在退出通知期间正常运行。
- 如果在退出通知期间(步骤 2a 期间)上下文未被取消并达到步骤 2b,则退出过程将继续到下一步。否则,退出通知将被中断,上下文立即被取消。
- 所有上下文线程通过从 Truffle 安全点抛出特殊的
ThreadDeath
退出异常而被强制停止。- 为了可靠地退出线程,语言需要确保
ThreadDeath
始终立即被重新抛出,并且客体语言的异常处理器和 finally 块不被运行。 - 嵌入器线程最终会向主机抛出一个
PolyglotException
,其中PolyglotException.isExit() == true
,且PolyglotException.getExitStatus()
等于最初作为TruffleContext.closeExited(Node,int)
首次调用的第二个参数指定的退出码。 - 请注意,从步骤 3 开始,退出过程与图中所示的取消过程相似,但取消过程使用一个特殊的
ThreadDeath
取消异常,并且抛给主机的PolyglotException
具有PolyglotException.isCancelled() == true
而不是PolyglotException.isExit() == true
。
- 为了可靠地退出线程,语言需要确保
- 所有已初始化语言都被终结。
- 为所有已初始化的语言调用
TruffleLanguage.finalizeContext(C)
。 - 在
TruffleLanguage.finalizeContext(C)
中运行任何客体代码,都会从第一个 Truffle 安全点抛出特殊的ThreadDeath
退出异常。 - 语言应跳过任何需要运行客体代码的终结操作。语言可以通过检查
TruffleLanguage.exitContext(C,ExitMode,int)
是否之前以ExitMode.NATURAL
调用,或者通过检查TruffleContext.isClosed()
是否返回false
来判断是否可以在TruffleLanguage.finalizeContext(C)
中运行客体代码。
- 为所有已初始化的语言调用
- 所有语言都被处置。
- 为所有语言调用
TruffleLanguage.disposeContext(C)
。
- 为所有语言调用
- 上下文被关闭。
如果 useSystemExit 被启用时的行为 #
- 退出由 TruffleContext.closeExited(Node,int) 触发。
- 与系统退出禁用时相同。
- 执行所有已初始化语言的退出通知 - TruffleLanguage.exitContext(C,ExitMode,int),其中
ExitMode.HARD
用作ExitMode
参数。- 与系统退出禁用时相同。
- 调用
System.exit(int)
来终止整个主机应用程序,提供最快的退出方式。- 传递给
System.exit(int)
的退出码是最初作为TruffleContext.closeExited(Node,int)
首次调用的第二个参数指定的退出码。
- 传递给
使用示例 #
SimpleLanguage 演示了硬上下文退出的用法。以下方面得到了演示:
- SLExitBuiltin 演示了触发上下文退出。
- SLRegisterShutdownHookBuiltin 演示了关机钩子(shutdown hooks)的注册,这些钩子在 SLLanguage 中定义的退出通知期间执行。
- SLExitTest 演示了上述内置功能的用法。