根据文档,GraalVM 项目中的原生图像编译器对动态代理有一些限制。既然Hibernate大量使用了代理,那么在提前编译好的项目中能正常工作吗?
Quarkus 项目好像说明可以,但是我的理解主要是基于Reddit post的一个说法
Hibernate ORM can now work even when compiled as GraalVM native images - just make sure you use Quarkus to build the application.
如果我不想(或不能)使用 Quarkus 怎么办?是否可以使用使用 Hibernate 的 GraalVM(和 SubstrateVM)编译 native 镜像应用程序?
Quarkus 实际上做了什么来启用/支持 Hibernate?
最佳答案
(免责声明:我是通过创建 Quarkus 扩展使 Hibernate ORM 在 GraalVM native 镜像上工作的人之一。我还领导 Hibernate 研发团队。)
感谢您有机会记录一些历史:)
最初我们没有使用 Quarkus,因为它还不存在。
我最初的原型(prototype)只是修补 Hibernate ORM 并堆积许多编译器开关以传递给本地镜像工具,硬编码在 bash 脚本中,直到我的演示应用程序工作。
这种方法的问题在于,许多此类标志实际上取决于 Hibernate ORM 的内部知识、域模型的细节、配置详细信息等的组合。
我开始记录这些事情,但它变得越来越复杂和多毛;不同的方面相互依赖;此外,我的演示应用程序相当简单,而实际应用程序的情况肯定会变得更加复杂……我认为我们无法编写一个既全面又“易于理解”的好文档。
为最终用户保持简单的另一种方法是“在您可能使用它们时启用对所有这些类的反射”,但我是一个优化狂,这会创建更大和臃肿的二进制文件,而不是仅并且专门包含您的应用程序真正需要的所有内容。
所以我们的团队决定编写一个工具来自动化这些细节......它变成了一个构建工具,可以分析您的应用程序以找出要使用的最佳开关。而不是只专注于 Hibernate ORM,我们创建了“扩展”的概念,它知道如何为其他库使用相同的技巧,这样您就可以从使用支持库组合的更复杂应用程序的高度优化的二进制文件中受益,不仅仅是 hibernate 。
显然,这是必要的,因为不同的库可能有相互冲突的需求,并且需要将每个其他库的编译器标志和最终用户的代码组合成一组一致的兼容标志。
所以这就是 Quarkus 成为一件事的方式:)
要查看其工作原理的详细信息,我建议您阅读指南和源代码:
我还对它在公开演讲中的运作方式进行了一些高层次的概述;来自 Devoxx UK 的录音很好
我的演讲专门讨论了 Hibernate ORM;我没有太多时间详细介绍它所做的所有事情,但在阅读实际代码以获取详细信息之前,它应该作为一个很好的介绍。
What if I don't want to (or can't) use Quarkus? Is it possible to compile a native-image application using GraalVM (and the SubstrateVM) that uses Hibernate?
这是一个公平的问题 - 这当然是可能的,但 Quarkus 团队很想知道为什么?
Quarkus 所做的所有工作大多只是构建时间;肯定它在这个阶段可能会受到限制,因为它是一个非常年轻的项目,但是如果您需要对其他任何东西的支持,那么为其核心(或其扩展)做出贡献应该比在构建脚本中硬编码复杂的编译器标志更容易。尤其重要的是,Quarkus 社区正在成为讨论如何解决可能受到 Graal 限制的任何障碍的好地方。
Hibernate ORM 的所有最复杂的补丁都已合并到 Hibernate 上游存储库中,因此所有重要的补丁都包含在任何最近的版本中。
假设你想远离 Quarkus(我不建议这样做,但假设你想学习......),你仍然需要修改反射规则,实际上 Quarkus 限制了一些功能,最值得注意的是一些细节仍然“正在进行中”,或者我们认为人们不应该再使用的东西:)
具体来说,我和我的队友都不是线程绑定(bind) session 的忠实粉丝。除非有人为它提供一个很好的案例,否则我不会对此实现支持:请打开一个功能请求,或者最好帮助为它提供一个很好的案例和补丁?
关于java - Hibernate ORM 是否与 GraalVM native 镜像编译兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56282460/