爪哇第11代国王坐在宝座上,俯视他的臣民。经过历代国王的努力,他的爪哇帝国正处于鼎盛时期。一众大臣见新王即位,立马上前奉承。“从后台到移动端,从移动端到大数据,帝国版图无边无际。”Thread部长率先定下了基调。“Java是企业级应用不可动摇的霸主,生态环境极其丰富,Spring已经统治了后端开发。”JVM老部长居然对Spring赞不绝口!“Java虚拟机性能强大,其他语言的虚拟机都是玩具。”春部长连忙回敬。...您已经听过数百次的老生常谈。国王有些恼火,挥手让众人退下。他决定带几个保镖,穿着微服离开王宫,到外面走走看看。1.微博私访走出京城大门,君王看到的是一望无际的码田。烈日下,无数Java码农在这里辛勤劳作,CRUD的工歌响彻云霄。王者仔细一看,果然码农用的工具是SpringBoot和SpringCloud。看来大臣说的是真的。前面的大树下,一个中年男人开了一家小茶馆,几个码农聚集在那里,休息,喝水,在树荫下聊天。国王悄悄走近。中年人拿着一把蒲扇,笑着说:大家知道吗,Java大难临头,你们可能会失业。一个戴着厚眼镜的码农笑得把茶水都吐了:哈哈哈,危言耸听,这怎么可能?中年男子缓缓说道:时代变了。Java原来特别适合大型服务器端应用,特别擅长跑高性能的时候。现在是云计算和微服务的时代。有了容器和集群,服务可以随时重启,微服务越来越小,可以用任何语言。另一位格子衫农说:也可以用Java写,SpringBoot很好,协议比配置更重要,内置服务器,一个jar包就可以运行。其余码农附和,国王暗暗点头。中年男子笑着说:云应用要求1.镜像小2.启动速度快,随时可用。Java能做到吗?厚眼镜的码农说:嗯,Java的docker镜像频繁上传G,冷启动太慢,每次都要等很久!格子衫说:Spring在启动的时候也用了太多的反射黑魔法,启动速度比较慢。中年男子说:是啊。带着一家小奶茶店,穿越到了Python王国、JavaScript王国、Go王国。那里没有这样的问题。非常适合云应用。你不妨去看看。他的话触动了这些Java程序员的心,他们开始窃窃私语,询问通往那些王国的路。国王看出中年人不厚道,便对侍卫开了个玩笑。保镖掀翻了小奶茶店,抱起中年人离开,留下几名码农目瞪口呆。2.三策之王召集春部长和JVM部长一起审问中年男子。King:你是谁,为什么要吓唬我,让我对年轻人产生误解?中年男人:小敏说的是实话。陛下,您可能被骗了。外界正在发生翻天覆地的变化。Java如果不与时俱进,就会岌岌可危。Spring部长和JVM部长意味深长的对视了一眼。国王不以为意,问道:“你有什么建议?”中年男人:小民有上策、中策、下策。陛下最想先听哪一个?国王:哦?三种策略?先说最坏的政策吧。中年人:最坏的政策是保持现状不变。春部长:等于什么都不说,中间政策呢?中年人:中策就是换Spring。当一个Spring应用程序启动时,它会扫描代码中的bean,并以反射的方式注册这些bean。这种方法花费的时间与应用程序中的代码量成正比,因此启动性能会很差。.如果将反射转化为编译时直接调用的类,应用程序的启动速度会大大提高。我的研究表明这种方法至少可以降低50%的成本,民间已经出现了一个叫做Micronaut的框架,实现了编译期依赖注入!春大臣一听这家伙要杀自己,顿时吓了一跳,连忙跪倒在地。他先是回顾了先辈如何用SpringMVC干掉Struts的英雄事迹,然后悄悄提到自己是如何与时俱进,用SpringBoot、SpringCloud、SpringWebFlux在微服务和响应式编程时代脱颖而出的。希望爪哇王能记住旧爱。国王转眼看了JVM大臣一眼:嗯,也许这个方法可以提高Spring应用的启动速度,但据我所知,JVM的启动速度也很慢,那怎么办呢?中年男人:这是我要讲的最好的政策。抛弃JVM,将Java程序编译成本地代码执行!“大胆!你要革命,要造反!”JVM大臣也忍不住了。“陛下,这种叛逆之徒,拉下他,处死他!”春部长也立刻火了起来。王者很清楚,20多年来,最强大的Java帝国就是字节码和JVM。现在,ZGC垃圾回收器的停顿时间不超过10ms,而且停顿时间不会随着堆的增加而增加。JVM的JIT也是精通的。它在运行时找到最热的代码,编译成本地二进制执行,几乎和C语言一样高效!相比之下,JavaScript和Python虚拟机能叫虚拟机吗?这只是一个玩具!为什么他们不强调停顿的时间长度?不过,这个策略非常大胆。云计算时代,真的需要JVM吗?国王陷入了沉思。3、放弃JVMJVM大臣见王不说话,又描述了一遍Java程序的生命周期。JVM初始化、应用程序初始化、应用程序预热、应用程序稳定关闭每个阶段都有重要的使命,尤其是在应用程序预热时,Java字节码会被编译成本地代码。“如果放弃JVM,前人的一切努力将不复存在!这将动摇我Java帝国的根基!”JVM部长福迪嚎啕大哭。java程序监控,extensions,jstat,jstack,jmap都没有用。调试时只能使用复杂的GDB汇编调试,非常麻烦。不过,编译成本地代码的好处也很明显。不存在冷启动问题,启动就是峰值。JVM大臣见王者依旧没有反应,决定抛出自己的王牌:“陛下,我Java帝国之所以能称霸世界,关键在于生态极其丰富。框架和类库涵盖所有后端开发的各个方面。”“而这些框架和类库都在大量使用反射,甚至使用动态代理,在运行时动态生成字节码。换句话说,这些东西无法在编译时确定,只能在运行时确定。”“比如对于Class,.forName("x.y.z")这样的代码在编译的时候怎么转成本地代码呢?”蒋真是又老又辣,JVM大臣第一时间抓住了最关键的地方,一脚把球踢给了仲青年。没想到,中年男子信心十足:“这个很简单,在做静态代码分析的时候,会发现x.y.z是一个需要加载的类,然后编译成本地代码!”“那要是这里不是字符串值,而是变量呢?Class.forName(someClassName)”JVM老头得意一笑,他已经挖坑了。“那就没办法了,我们得让用户在配置文件中告诉我们哪些类需要编译成本地代码。“哈哈哈,说白了,一个框架用了那么多反射,你怎么可能在配置文件里让用户提前告诉你?””中年男子也不甘示弱:“那我可以开发一个程序,让用户的程序运行一次。我的程序监控用户程序中哪里用到了反射,然后自动生成配置文件!”“”程序分支那么多,跑一遍就能找到所有用到反射的地方?JVM大臣转身对着国王坚定的说道:“陛下,这个方法肯定是行不通的。”“”寡妇认为,这其实是不满足闭包原则的,除了反射,还有动态代理,JNI,序列化,等Java代码使用这些特性时,静态编译会遇到问题,需要寻找变通办法,变通办法不能覆盖所有情况。真是高明,一瞬间就上升到了理论层面,我可望而不可及。”JVM连忙受宠若惊。4.编译“陛下,拉下这个造谣惑众的家伙!春大臣提醒道。”虽然Java的动态特性不能完美满足闭包原则,但是静态编译确实很有吸引力。请告诉我怎么做。”国王没有理会春部长,继续问中年人。main函数,然后静态编译器就从这里开始分析程序的可达性。“scope,把所有可达的函数和一小段运行时支持代码编译成一个nativeimage。”“可笑,可笑,你忘了Java是一个面向对象语言,多态性无处不在?”JVM大臣讽刺道。“我举个例子,看你是如何做静态分析的。”voidprocess(Listemployees){intsize=employees.size();...}”这个List是JDK的一个接口,JDK有很多实现类(ArrayList、LinkedList、Vector等),我们的项目中也有很多自定义的List实现类。实际的员工类型只能在确定runtime.你静态分析的时候怎么确定的?”“你不会把List的所有实现类都编译成二进制码吧?”Spring大臣立马添油加醋。“如果是这样的功能voidprocess(Objecto),Object是所有类型的根,你要编译所有的类吗?哈哈哈!”JVM部长忍不住笑了起来。“那肯定不行,我有一个绝活,叫做‘方向性分析’,不用运行程序,就能在运行时找到一个类型变量可能的类型。”中年男子并不着急。定向分析?春部长和JVM部长又对视了一眼,明白中年男人不会多说什么。国王盯着中年男子问道:“你叫什么名字?”什么名字?“小人名叫格拉尔。”国王想了想。在云计算时代,随着容器技术的出现,一次编写,随处运行不再重要。相反,Java确实面临镜像大、冷启动慢的严峻挑战。将Java代码编译成本地代码需要放弃祖辈的基础,或许才是破局的关键。身为新一代王者,我绝不能固步自封,更不能成为亡国之王。我必须尝试所有可能的方向。想到这里,国王对中年男子说道:“好吧,Graal,我已经明白你的用意了,现在我给你派出一队专门从事静态编译技术的人!Spring部长,你必须5、结束几个月后,中年人推出了一个新的虚拟机GraalVM,这个VM很有野心,不仅实现了Java编译成本地代码,还支持JavaScript、Ruby、R、Python等语言Spring大臣虽不情愿,但圣旨不可违,他再次与时俱进,推出SpringNativewithGraalVM,将Spring应用编译成原生镜像。SpringNative的启动时间有增加了50倍,瞬间达到峰值,内存使用减少了5倍。Java暂时度过了云计算时代的危机,未来又将面临怎样的挑战?
