在云原生时代,Java程序是有很大的劣势的,为什么这么说呢?你看Java的一个最简单的hello world都要大几十M的内存,启动也不不快。以最流行的spring boot/spring cloud微服务框架为例,启动一个已经优化好,很多bean需要lazy load的application至少需要3-4秒时间,内存需要几百M,业务逻辑稍微复杂一点点,没有1G以上的内存是很难满足业务的需要呢?
那么在云原生时代,Java会落后吗?答案到现在,笔者也不好说,不过大概率不会,为什么呢?因为java社区没有闲着,弄出来很多好玩的黑科技。下面我就一个充满黑科技的JVM介绍给大家,用他能帮助我们让Java程序的启动速度加快100倍,内存只需要原来的五分之一,甚至更少。
还等什么,让我们开始吧。
一、Graalvm的介绍
Graal VM是2018年Oracle开发的下一代JVM实现,被官方称为“Universal VM”和“Polyglot VM”,这是一个在HotSpot虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用,这里“任何语言”包括了Java、Scala、Groovy、Kotlin等基于Java虚拟机之上的语言,还包括了C、C++、Rust等基于LLVM的语言,同时支持其他像JavaScript、Ruby、Python和R语言等等。Graal VM可以无额外开销地混合使用这些编程语言,支持不同语言中混用对方的接口和对象,也能够支持这些语言使用已经编写好的本地库文件。
主要特性包括:
- 高性能的现代Java
- 占用资源少,启动速度快
- JavaScript, Java, Ruby以及R混合编程
- 在JVM上运行原生语言
- 跨语言工具
- JVM应用扩展
- 原生应用扩展
- 本地Java库
- 数据库支持多语言
- 创建自己的语言
二、Graalvm安装及环境配置
GraalVM包括社区版和企业版,我们以社区版为例,截取当前2020年6月份,最新的Release版本为:Graalvm Community 20.1.0,下载地址:https://www.graalvm.org/downloads/
不过社区版需要会让你跳转到github进行下载,github下载很慢,需要科学翻墙才行。
2.1 在Windows 10平台上安装
请按照以下步骤在x86 64位Windows上安装GraalVM Community Edition。
-
GitHub上的GraalVM Releases存储库。根据电脑配置,选择graalvm-ce-java8-windows-amd64-20.1.0.zip或graalvm-ce-java11-windows-amd64-20.1.0.zip并下载。
-
将文件压缩到文件系统,比如 d盘根目录。
-
配置
JAVA_HOME
和PATH
环境变量。在Windows 7、8和10中,通过命令行设置环境变量的工作方式相同。-
将GraalVM bin文件夹添加到
PATH
环境变量:setx /M PATH "d:\graalvm-ce-java8-20.1.0\bin;%PATH%"
-
设置
JAVA_HOME
环境变量以解析到GraalVM安装目录:setx /M JAVA_HOME "d:\graalvm-ce-java8-20.1.0"
请注意
/M
,等同于的标志-m
需要管理员权限的命令行。
-
-
重新启动命令提示符以重新加载环境变量。然后使用以下命令检查变量设置是否正确:
echo %PATH% echo %JAVA_HOME%
java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 25.252-b09-jvmci-20.1-b02, mixed mode)
2.2 使用gu工具安装 native image
要在GraalVM Community Edition中添加对Python,R,Ruby或WebAssembly语言解释器的支持,请使用功能[gu
实用程序]GitHub上有一个由Oracle(gu available
)维护的组件目录,您可以从中按名称安装组件:
gu install ruby
gu install r
gu install python
gu install wasm
要安装LLVM工具链组件,请运行:
gu install llvm-toolchain
要安装GraalVM本机映像,请运行:
gu install native-image
在Windows上使用native images的先决条件
要在Windows上使用本机映像,请遵循其他建议。所需的Microsoft Visual C ++(MSVC)版本取决于GraalVM所基于的JDK版本。对于基于JDK 8的GraalVM分发,您将需要MSVC 2010 SP1版本。推荐的安装方法是使用Microsoft Windows SDK 7.1:
-
GRMSDKX_EN_DVD.iso
从Microsoft下载SDK文件。 - 通过
F:\Setup\SDKSetup.exe
直接打开安装图像。
对于基于JDK 11的GraalVM分发,您将需要MSVC 2017 15.5.5或更高版本。
对于基于JDK 11和JDK 8的GraalVM发行版,共同的最后一个先决条件是适用于您的Visual Studio版本的正确的Developer Command Prompt。即,它应该是x64本机工具命令提示符。使用Visual Studio 2017或更高版本。
三、spring boot之Graalvm
其实在2019年spring 团队已经开始作手支持graalvm的native image功能。就在前几天(2020-6-10)spring-graalvm-native 发布了0.7.0版本。Spring团队承诺对Graal VM的支持必须在2020年10月之后才会正式提供,但现在的我们其实已经可以使用Graal VM来(实验性地)运行Spring、Spring Boot、Spring Data、Netty、JPA等等的一系列组件(不过SpringCloud中的组件暂时还不行)。
接下来,我们将尝试使用Graal VM来编译一个标准的Spring Boot应用。
3.1 准备工作
首先,我们先假设你准备编译的代码是“符合要求”的,即没有使用到Graal VM不支持的特性,譬如前面提到的Finalizer、CGLIB、InvokeDynamic这类功能。然后,由于我们用的是Graal VM的Java 8版本,也必须假设你编译使用Java语言级别在Java 8以内。
spring-graalvm-native的0.7版本基于刚刚发布的Spring Boot 2.3和上面提到的Graalvm 20.1.0 版本。请将你的pom.xml中的Spring Boot版本修改如下(假设你编译用的是Maven,用Gradle的请自行调整):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0</version>
<relativePath/>
</parent>
同时在pom.xml中增加spring对graalvm的支持(别忘了现在也添加Spring Milestones存储库,因为现在还没有通过Maven Central发行)。):
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.7.0</version>
</dependency>
...
<dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
由于GraalVM不支持GCLIB代理,因此Spring Boot需要使用JDK代理。因此,请使用proxyBeanMethods = false
@SpringBootApplication类的属性:
@SpringBootApplication(proxyBeanMethods = false)
public class SpringBootHelloApplication {
...
}
3.2 开始native image成本地原生程序
现在,我们几乎已经准备好一切,最终可以运行native-image
命令。这是一个示例,该示例基于提到的实现Reactive Spring Boot Web应用程序的示例项目。把java程序编译成本地程序,是一个很难一次性成功的事情,它取决于要编译为GraalVM本机映像的Spring Boot应用程序的类型!因此,最好的方法是从spring-graal-native项目的示例项目中获得一些参考和提示。
开始吧:
- 先maven编译,这部很简单,我们都很熟悉
mvn clean package
- 运行native image命令进行本地原生编译
native-image \
-H:+TraceClassInitialization \
-H:Name=spring-boot-graal
-H:+ReportExceptionStackTraces \
-Dspring.graal.remove-unused-autoconfig=true \
-Dspring.graal.remove-yaml-support=true \
-cp target/spring-boot-graal.jar
这个过程可能有点长,建议你起来喝杯水或者喝杯咖啡!这需要一些时间,具体取决于您的硬件!示例项目大约需要3-4分钟。如果一切顺利,您将在中找到本地编译的Spring Boot应用程序/target/spring-boot-graal
。只需使用以下命令运行它:
./target/spring-boot-graal
=============================
网友评论