Posts 在 macos 上试玩 graalvm & native Image
Post
Cancel

在 macos 上试玩 graalvm & native Image

本篇就不继续啰嗦为什么要使用 graalvm + native-image ,以下有几篇优秀的参考文章会更加详细的阐述原因:

安装 & 配置

!!! 如果需要了解更多种安装及配置方案的可以跳转到官网的 Getting Started,其实也讲的蛮详细的。


下例直接 Homebrew 进行安装,点开跳转原始出处

1
brew cask install graalvm/tap/graalvm-ce-java8

配置命令行,注意下例只作用于当前窗口环境,如果你想要永久生效请配置自己的 ~/.bashrc 或者 ~/.zshrc 中的环境变量(关键字:如何配置 JDK 环境变量)

1
export PATH="$PATH:/Library/Java/JavaVirtualMachines/graalvm-ce-java8-20.0.0/Contents/Home/lib/installer/bin/"

安装 Native-Image - 默认 brew 方式不会自动安装,不过官网提到了 GraalVM Updater 来安装额外的工具,点开跳转原始出处

1
2
gu available
gu install native-image

简单 Java 示例

保存下例文件到 HelloWorld.java

1
2
3
4
5
public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

编译与运行,可能 Native-Image 需要花一些时间,最后输出的文件在 ~2M 左右

1
2
javac HelloWorld.java
native-image HelloWorld

输出文件简要说明:

  • HelloWorld.class - 需要依赖 JVM 启动

    1
    
    >java HelloWorld
    
  • helloworld - 平台可执行文件,不需要依赖 JVM 启动,直接运行

    1
    
    ./helloworld
    

JavaEE 示例

主要依赖 TomcatGraalVM + Native-Image 支持,待定…

TBD

SpringBoot 示例

随着官方释出 spring-native-beta 的消息,本段的试玩围绕该内容展开(更多参考:Spring Native 官方文档):

I. 创建 demo 项目(以下使用的 Spring Boot CLI 命令行进行操作的,可视化方法可以参考:https://start.spring.io/)

1
  spring init -a demo -g com.github.demo -d=web,native demo/

II. 进入到 demo 项目并执行如下命令(确保本地 Docker 启动,并且分配的虚拟机内存需要大于 5Gb)

1
   mvn spring-boot:build-image -DskipTests

PS: 该过程需要花费大量的时间在 Maven 依赖, Docker Builder 镜像,GraalVM 及 Native-Image 下载上面

III. 上述命令运行成功之后,可以利用下述的方式进行启动镜像(非常明显可以感觉得到启动速度的提升)

1
  docker run --rm -p 8080:8080 demo:0.0.1-SNAPSHOT
输出日志 2021-03-29 03:49:37.730 INFO 1 --- [ main] o.s.nativex.NativeListener : This application is bootstrapped with code generated with Spring AOT . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.4) 2021-03-29 03:49:37.731 INFO 1 --- [ main] com.github.demo.demo.DemoApplication : Starting DemoApplication using Java 11.0.10 on 3eee6ce1f81b with PID 1 (/workspace/com.github.demo.demo.DemoApplication started by cnb in /workspace) 2021-03-29 03:49:37.731 INFO 1 --- [ main] com.github.demo.demo.DemoApplication : No active profile set, falling back to default profiles: default 2021-03-29 03:49:37.755 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) Mar 29, 2021 3:49:37 AM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-nio-8080"] Mar 29, 2021 3:49:37 AM org.apache.catalina.core.StandardService startInternal INFO: Starting service [Tomcat] Mar 29, 2021 3:49:37 AM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet engine: [Apache Tomcat/9.0.44] 2021-03-29 03:49:37.757 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 26 ms Mar 29, 2021 3:49:37 AM org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring embedded WebApplicationContext 2021-03-29 03:49:37.766 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' Mar 29, 2021 3:49:37 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-nio-8080"] 2021-03-29 03:49:37.775 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2021-03-29 03:49:37.776 INFO 1 --- [ main] com.github.demo.demo.DemoApplication : Started DemoApplication in 0.049 seconds (JVM running for 0.053)

IV. 最后,我们利用下述命令进行访问测试

1
  curl http://localhost:8080 -v
输出日志 * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8080 (#0) > GET / HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.64.1 > Accept: */* > < HTTP/1.1 404 < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Content-Type: application/json < Transfer-Encoding: chunked < Date: Mon, 29 Mar 2021 03:49:32 GMT < * Connection #0 to host localhost left intact {"timestamp":"2021-03-29T03:49:32.060+00:00","status":404,"error":"Not Found","message":"","path":"/"}* Closing connection 0

TBD

Netty 示例

TBD

结论

综上所述的各种示例是需要框架本身均兼容 GraalVM + Native-Image 的限制的,那么就意味着 Java 生态环境中有很多第三方的框架和库都会面临兼容性等问题;但尽管如此,这种技术所带来的好处是利大于弊的,否则在容器环境中 Java 的竞争力就不高了 - 尤其是大公司成百上千的团队使用传统的 Java 部署服务的时候会消耗/浪费大量的内存空间(内存就是金钱,具体可以自行搜索查看内存的发展史以及其垄断市场),普遍的现象就是 CPU 与 RAM 的比例始终不协调,并且启动的时候 CPU 总是一下子飙升后降。

This post is licensed under CC BY 4.0