当前位置: 首页 > 科技观察

不需要jre来运行Java?你没看错!

时间:2023-03-20 13:12:44 科技观察

今天要介绍的是spring-native,它可以让你的springboot程序体验graalvm编译器的特性,将你的应用直接编译成native!无需安装jre,您的应用程序将和exe一样,直接在目标机器上运行!启动时间不到1秒。为了体验这个功能,我们从springboot拿了一个demo。https://start.spring.io/在这里选择这个实验性的特性SpringNative。下载后,可以使用maven打包测试。mvnspring-boot:build-imagegradlebootBuildImage看看这无敌的启动速度……0.038秒……几乎是瞬间!惊人的!这一切都归功于graalvm编译器。不过至少得把JDK升级到11才能使用,算是给Java8用户换了个驱动。当然,只有SpringBoot2.4.5以后的版本才支持SpringNative。什么是GraalVM?graalvm也是一个oracle项目。它的代码地址是:https://github.com/oracle/graal项目地址是:www.graalvm.org/docs/graalvm是一个想要统一世界的虚拟机。因为它和HotSpotVM相比,它还可以运行其他语言,如ruby、python、php等。它是一个新的JVM,不同的是,由于适配,它可以让不同的语言来在同一个虚拟机下运行。看看下图就知道graalvm有多么雄心勃勃。这还没完,它最吸引人的地方在于它可以直接将应用代码打包成原生的二进制可执行代码,甚至在运行时都不需要JVM!大家都知道native和runninginvm是完全不同的两个档次,不然也不会有jit这样牛逼的技术。就连安卓和iOS都知道,原生应用的流畅度远高于运行在monotouch或hybrid上的应用。对于追求性能的企业级应用来说,这个功能比较实用。令人惊讶的是,它为每种语言实现了一个交流桥梁。比如我看好js中的某个库。无需重新开发一个,直接在Java中使用即可。这是因为graalVM制定了跨语言互操作协议来保证跨语言互操作。现在大多数平台都支持这个功能。什么是原生?考虑以下代码。publicclassExample{publicstaticvoidmain(String[]args){Stringstr="NativeImageisawesome";Stringreversed=reverseString(str);System.out.println("Thereversedstringis:"+reversed);}publicstaticStringreverseString(Stringstr){if(str.isEmpty())returnstr;returnreverseString(str.substring(1))+str.charAt(0);}}一般我们直接这样运行,或者打成jar包。javacExample.javajavaExample但是我们还可以更进一步,就是将类文件本地化。执行native-imageExample时,只需要输入./Example即可。有什么好处?使用本机编译的应用程序可以在几秒钟内启动,运行速度更快,占用的内存更少。更符合微服务、k8s等主流部署方式。但它也与传统的JVM有很多不同,主要体现在:系统的性能分析会在编译阶段给出无用的部分和代码。代码不会编译,直接移除,这得益于之前java版本的模块化,需要提前转换反射、资源、动态代理。类加载没有延迟。在编译阶段不会延迟加载类路径。固定的类不会被延迟加载,启动时会被放入内存。虽然native有很多好处,但是它的编译时间很长,因为需要进行大量的代码静态分析,这也是所有native程序的通病。结束这种thinjar的思路,是不是觉得Java的开发越来越像golang了?docker镜像也会因为这个变化变得更小更纯粹,脱离jre的Java应用也越来越像一个真正的程序。但遗憾的是,这种编译成native的思路虽然不错,但现阶段还是无法与golang抗衡,主要是编译器的差异。希望graalvm能够再接再厉,继续和java一起飞翔几十年,养活我的三代子孙!