GraalVM

屌炸天,Oracle 发布了一个全栈虚拟机 GraalVM,支持 Python! (qq.com)

springNative

Spring-native 实战 - 知乎 (zhihu.com)

(32条消息) 王炸!!Spring 终于对 JVM 动手了…_Java技术栈的博客-CSDN博客

JVM 的程序运行时间长,是因为存在虚拟机的初始化和类加载过程,如果将字节码直接编译成原生代码,则可以彻底解决这些问题。同时因为没有即时编译器在运行时编译,所有代码都在编译期编译和优化。因为少了 Java 虚拟机、即时编译器这些额外组件,原生程序也能够省去它们原本消耗的内存资源和镜像体积。

Java 支持提前编译最大的困难,在于 Java 是一门动态链接的语言,它假设程序的代码空间是开发的,允许在程序的任何时候通过类加载器去加载新的类,作为程序的一部分。要进行提前编译,就必须放弃这部分动态性,所有要运行的代码必须在编译期全部可知。这样动态加载、反射(通过反射可以调用在编译期不可知的方法)、动态代理、字节码生成库(如 CGLib)等一切会运行时产生新代码的功能都不再可用。

  • 对于反射,需要用户在编译期,通过配置文件或编译器参数的形式,明确告知编译器程序代码中哪些方法只通过反射来访问的。
  • 用户往往不知道动态生成字节码的具体信息,这些只能由程序去做妥协。默认情况下,每一个 Spring 管理的 Bean 都要用到 CGLib。从 Spring Framework 5.2 开始增加了@proxyBeanMethods 注解来排除对 CGLib 的依赖,仅使用标准的动态代理去增强类。

当然 Spring Native 遇到的问题有很多,且仍然处于试验阶段。以原生方式运行后,启动时间是能够缩短很多,但是程序的运行效率还是若于传统基于 JVM 的方式,且编译成原生程序代码的时间更长。

转载自 SpringNative:把Spring项目编译成原生程序 - 知乎 (zhihu.com)

本机不同于JVM:类路径在构建时是固定的,例如需要反射或资源进行配置,没有类延迟加载(可执行文件中附带的所有内容在启动时都加载到内存中),并且可以调用一些代码在构建时。

为了充分体现这些特性并允许Spring应用程序在本机上以最大的兼容性和最小的占用空间运行,Brian Clozel在此版本中引入了Spring提前(AOT)Maven和Gradle插件,它们可以提前执行您的应用程序上的转换。

第一种转换旨在基于由惊人的Andy Clement设计和实现的推理引擎来生成GraalVM本机配置(反射,资源,代理,本机映像选项),该引擎了解什么是Spring编程模型和基础架构。例如,对于每个由注释的类@Controller,一个条目将被添加到生成的reflect-config.json文件中。

无法推断出某些本机配置,对于这些情况,我们引入了本机提示注释(有关更多详细信息,请参见Javadoc),这使Spring Native可以比基于常规JSON的本机图像配置更可维护,类型安全和灵活地支持本机配置。例如同春本地MySQL驱动支持提供线索,让一代机映像正确的条目reflect-config.json,resource-config.json以及native-image.properties如下:

NativeHint(
    trigger = Driver.class,
    options = "--enable-all-security-services",
    types = @TypeHint(types = {
       FailoverConnectionUrl.class,
       FailoverDnsSrvConnectionUrl.class,
       // ...
    }), resources = {
    @ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),
    @ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",
                      isBundle = true)
})
public class MySqlHints implements NativeConfiguration {}

NativeConfiguration和其他动态配置机制允许更强大的和动态的配置生成,但要注意它们的API将在即将到来的版本演变了很多。

Spring开发人员还可以使用特定于应用程序的本机提示直接注释其@Configuration或@SpringBootApplication类,例如,Book通过诸如RestTemplate或的编程API将类序列化为JSON WebClient:

@TypeHint(types = Book.class)
@SpringBootApplication
public class WebClientApplication {
    // ...
}

与提前转换系统一起使用时,最后一种可能是最强大的机制是使用Spring Boot部署模型与GraalVM native结合引入的封闭世界假设自动生成本机优化代码(源代码和字节码)的功能。图像特征。这里的目标是通过使用本机图像编译器可以开箱即用地分析的代码构造来限制所需的额外本机配置的数量,以提高兼容性,并通过减少反射所需的配置数量来减少占用空间,资源或代理。一个具体的例子是各种形式的提前转换spring.factories (Spring Boot背后的扩展机制)到优化的程序设计版本,该版本不需要反射,并且可以在应用程序的上下文中过滤掉不必要的条目。

这只是Spring AOT的开始,我们打算向[@Configuration功能配置中添加更强大的转换,以通过提前分析来替换运行时反射,该提前分析将自动生成配置类,这些配置类将使用lambda和方法引用之类的程序化构造。这将使GraalVM本机图像编译器可以立即了解Spring配置,而无需任何反射配置或*.class资源。

要记住的一个关键点是,在使用Spring Native时,默认情况下在JVM上也会使用AOT生成的代码,以允许您使用JVM允许的短反馈循环来行使“本机友好的代码路径”。您的调试器和所有常规工具。

尽管Spring AOT转换当前主要由本机需求驱动,但是其中许多不是本机特定的,并且可能其中一些可以提供优化以在JVM上运行Spring Boot应用程序。与此类主题一样,重要的是数据驱动,以便我们测量效率和绩效来决定我们的决策。

我们可能会改进IDE的集成,现在确保在IDE中运行应用程序之前,请先阅读相关文档以进行潜在的手动配置步骤,以更新生成的源代码。

5 结论
Spring战略要本地化有两个主要支柱。第一个是使Spring基础结构适应本机,而无需对数百万个现有的Spring Boot应用程序进行重大更改。其中包括我们在Spring顶级项目中所做的更改,以使其对本机友好,@NativeHint我们将在Spring Native中成熟的基础架构(例如)和Spring AOT构建插件。

第二个支柱比Spring本身更广泛,native是一个具有与JVM不同的特性的平台,但是Java生态系统需要尽可能地一致,以避免两种非常不同的Java风格,这将难以维护。这就是为什么我们与GraalVM团队进行深入合作以缩小这一差距的原因。在接下来的几个月中,这项合作将专注于为更广泛的JVM生态系统改善本机测试和本机配置。

版权声明:本文为CSDN博主「公众号-老炮说Java」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_17231297/article/details/116399698

Spring Native 0.10.0 新特性
1、支持 Gradle 插件
以前仅提供 Maven 插件支持,现在终于可以支持官方 Gradle 插件了。

并且,还提供了新的构建工具(native-build-tools):

github.com/graalvm/nat…

它取代了之前的 native-image-maven-plugin 插件,它可以通过本地原生镜像编译器来构建和测试你的原生应用。

这个升级就感觉有点大,意味着之前那个插件的玩法就行不通了,需要用这个新的构建工具插件。。

2、支持原生测试
现在可以使用 mvn -Pnative test 或 gradle nativeTest 以原生镜像的方式运行 JUnit 5 单元测试用例。

另外,Spring Native 现在也添加了单元测试初始化支持,因此以 @SpringBootTest 编写的单元测试用例也可以作为原生镜像运行。Spring Boot 单元测试不清楚的,可以关注公众号:Java技术栈,看看栈长写的教程。

3、支持基于类的代理
我们都知道,原生镜像需要在构建时就定义代理,在前面的 Spring Native 版本中,Spring Native 也只能支持基于接口的 JDK 代理,不支持通过 CGLIB 基于普通类的代理,因为 Spring Native 的原生特性就不能支持在运行时生成字节码。

// Typical security use case of a class proxy now supported on native
@Service
public class GreetingService {

public String hello() {
    return "Hello!";
}

@PreAuthorize("hasRole('ADMIN')")
public String adminHello() {
    return "Goodbye!";
}

}

但是从 Spring Native 0.10.0 这个版本开始,基于普通类的代理也可以搞定了,现在可以在构建时通过 @AotProxyHint 注解来生成类的代理,这真是一个大的突破,牛皮!!!

需要注意的是:

以前的 @ProxyHint 已重命名为 @JdkProxyHint,以避免混淆。

它支持安全性、事务、以及其他基于普通类的代理机制,后续也将改进对此类模式的自动检测,以减少大量所需的显示提示。
————————————————
版权声明:本文为CSDN博主「大老二在不在」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41875978/article/details/118390536

Last modification:May 25, 2022
如果觉得我的文章对你有用,请随意赞赏