查看原文
其他

Java要抛弃祖宗的基业,Java程序员危险了!

The following article is from 码农翻身 Author 码农翻身刘欣

第11代Java国王坐在宝座上,俯视着臣民。


经过历代国王的励精图治,他的Java帝国正处于巅峰状态。


一群大臣看到新王登基,马上上来拍马屁。


“从后端到手机端,从手机端到大数据,帝国疆域无边无际。” 线程大臣率先定了基调。


“Java是企业级应用无可撼动的霸主,生态环境极大丰富。Spring已经统治了后端开发。” 年迈的JVM大臣居然夸起Spring来!


“Java虚拟机性能强大,其他语言虚拟机都是玩具。”  Spring大臣赶紧投桃报李。


......


都是一些听过几百遍的、老掉牙的东西。


国王听得有些烦,挥手让众人退下。


他决定带几个保镖,微服出宫,到外边亲自走一走,看一看。



1微服私访


走出都城大门,国王看到了一望无际的代码田地。


烈日下,无数的Java码农在这里辛苦劳作,CRUD的劳动号子响彻云霄。 


国王走近一看,果然,码农们用的工具都是SpringBoot和Spring Cloud,看来大臣所言不虚。


前面的大树下,一个中年人开着小茶铺,几个码农聚在那里,一边休息喝水、一边乘凉聊天。 



国王悄悄走近。


中年人打着蒲扇,笑眯眯地说:诸位,你们知不知道,Java已经大祸临头,你们有可能要失业了。


一个戴着厚厚眼镜的码农笑得把茶都喷了出来:哈哈哈,危言耸听,这怎么可能?


中年人慢悠悠地说:时代变了,原来的Java特别适合大规模的服务器端应用,尤其擅长时间高性能运行。现在是云计算时代,微服务时代,有了容器,集群,服务可以随时重启,并且微服务越来越小,用什么语言都可以。


另一个花格子衬衫码农说:那也可以用Java写啊,SpringBoot挺好的啊,约定重于配置,内置服务器,一个jar包就跑起来。 


其余几个码农纷纷附和,国王也暗自点头。 


中年人笑道:云端应用要求1. 镜像小  2. 启动速度快,即起即用。Java能做到吗?


厚眼镜码农说:嗯,Java的docker镜像动辄上G, 冷启动实在太慢了,每次都得等半天!


花格子衬衫说:还有Spring启动时用了太多的反射黑魔法,启动速度更慢。


中年人说道:这就对了,我带着小茶铺游历过Python王国、JavaScript王国,Go王国,人家那里就没有这样的问题,非常适合云端应用,你们不妨去看看啊。


一番话说得这几个Java码农动了心,开始窃窃私语,打探去那些王国的道路。


国王意识到这个中年人来者不善,给保镖使了个颜色。


保镖掀翻小茶铺,扭起中年人就走,留下几个码农目瞪口呆。



2三个计策


国王召来Spring大臣和JVM大臣,一起审问这个中年人。


国王:你是何人,为什么在那里危言耸听、鼓惑我朝年轻人?


中年人:小民说的都是事实啊,陛下,您可能被蒙蔽了,外界正在发生翻天覆地的变化啊,Java如果不与时俱进,岌岌可危啊。


Spring大臣和JVM大臣互相看了一眼,意味深长。


国王倒不在意,问道:你有什么建议? 


中年人:小民有一个上策、中策和下策,陛下想先听哪一个?


国王:哦?三个计策?先说说下策。


中年人:下策自然是保留现状不变。


Spring大臣:相当于没说,中策呢?


中年人:中策就是改Spring,Spring应用在启动时会扫描代码中的bean,然后用反射的方式注册bean,这种做法的耗时与应用的代码量成正比,所以启动性能会很差。


如果在编译时把反射转化为直接调用的类,将会大幅提升应用的启动速度。我的研究显示,这种办法至少可以将成本降低50%,并且民间已经出现了一个叫做Micronaut的框架,它已经实现了编译期的依赖注入!



Spring大臣一听这家伙要把自己干掉,大惊失色,赶紧跪倒。


他先回顾了祖上如何用SpringMVC干死Struts的英勇事迹,又不动声色地提起自己如何与时俱进,用SpringBoot、Spring Cloud,Spring WebFlux在微服务时代和反应式编程时代勇立潮头。希望Java国王能念起旧情。


国王眼珠一转,看了一眼JVM大臣:好吧,也许这种办法能提升Spring应用的启动速度,但是据我所知JVM的启动速度也很慢,这又该怎么办?


中年人:这就是我要说的上策了,抛弃JVM,把Java程序编译成本地代码来执行!



“大胆!你这是要革命,要谋反!” JVM大臣忍不住了。


“陛下,这等狂悖之徒,拉下去问斩吧!” Spring大臣也立刻拱火。


国王心里很清楚,二十多年了,Java帝国最厉害的无过于字节码和JVM,如今ZGC垃圾回收器停顿时间不超过10ms,停顿时间还不会随着堆的增大而增大,JVM的JIT也炉火纯青,在运行时找到最热点的代码,编译成本地二进制执行,效率直逼C语言!


相比之下,JavaScript和Python虚拟机能叫虚拟机吗?玩具而已!它们怎么不强调自己的停顿时长?


不过这个计策倒是非常大胆,云计算时代,真的需要JVM吗? 


国王陷入沉思。 



3抛弃JVM


JVM大臣看到国王不说话,又描述了一遍Java程序的生命周期。


1.JVM初始化 

2. 应用初始化

3.应用预热

4.应用稳定

5.关闭



每个阶段都有着重要使命,尤其是应用预热的时候,会把Java字节码编译成本地代码。


“如果抛弃JVM,前辈们所做的所有努力都不复存在!这会动摇我Java帝国的国本啊!” JVM大臣伏地干嚎。


Java程序监控、扩展、jstat、jstack、jmap都用不了了。


调试的时候,也只能用复杂的GDB汇编调试,非常麻烦。


但是编译成本地代码,好处也非常明显,没有冷启动问题,启动即巅峰。


看到国王依然没有反应,JVM大臣决定抛出杀手锏:


“陛下,我Java帝国之所以能称雄世界,关键就是生态极其丰富,框架和类库覆盖了后端开发的所有方面。”


“而这些框架和类库中在大量地使用反射,甚至用动态代理在运行时动态生成字节码,换句话这些东西在编译时根本无法确定,只有到运行时才能确定。”


“举个例子,对于Class.forName("x.y.z")这样的代码,如何编译时就把它变成成本地代码?” 


姜果然是老的辣,JVM大臣一下子就抓住了最关键的点,把皮球踢给了中年人。


没想到中年人胸有成竹:“这非常简单,在做静态代码分析的时候我会发现x.y.z是个需要被装载的类,然后把它也编译成本地代码!”


“那如果这里不是个字符串的值,而是一个变量呢?Class.forName(someClassName)”  JVM老头得意地笑,他早就挖好了坑。 


“那就没办法了,只好让用户在配置文件中告诉我们哪些类需要编译成本地代码了。”


“哈哈哈,说得轻巧,一个框架用了那么多反射,你让用户在配置文件中全部提前告诉你,怎么可能?”


中年人不甘示弱:“那我可以开发一个程序,让用户的程序运行一遍,我的程序监控用户的程序哪些地方用了反射,然后自动生成配置文件!”


“程序那么多分支,你运行一遍就能找到所有用到反射的地方?”


JVM大臣转向国王,斩钉截铁地说:“陛下,此法断不可行。”


“寡人觉得这其实就是不满足封闭性原则。除了反射之外,还有动态代理,JNI,序列化等,当Java代码使用这些特性的时候,静态编译就会遇到问题,需要想变通办法,而变通办法又无法覆盖所有情况。”


国王果然是国王,高屋建瓴。


“陛下真是英明,一下子就上升到了理论层面,我等望尘莫及。” JVM赶紧拍马屁。



4编译


“陛下,把这个散播谣言,鼓惑人心的家伙拉下去宰了吧!” Spring大臣提醒道。 


“虽然Java的动态性无法完美满足封闭性原则,但是静态编译确实是非常诱人,你说说,具体怎么做。” 国王不理Spring大臣,继续询问中年人。


“这个嘛,小民有个基本的思路,就是由用户指定程序入口,嗯,相当于main函数,然后静态编译器从这里开始分析程序的可达范围,把所有的可达的函数和一个小的运行时支持代码编译成native image。


“可笑啊可笑,你难道忘记了Java是个面向对象的语言,多态无处不在?” JVM大臣讽刺。


“我给你举个例子,看看你怎么做静态分析。”

void process(List employees){ int size = employees.size(); ......}


“这个List是JDK的一个接口,JDK有很多实现类(ArrayList,LinkedList,Vector等),我们的项目也有很多自定义的List实现类,employees的实际类型只能在运行时确定,你的静态分析如何确定呢?”



“你不会把List的所有实现类都给编译成二进制代码吧?”  Spring大臣马上添油加醋。


“如果是这样的函数 void process(Object o) ,Object是所有类型的根,难道你要编译所有的类?哈哈哈!” JVM大臣不由得大笑起来。 


“那肯定不行,我有个独门绝技,叫‘指向性分析’,可以在不运行程序的情况下,找到一个类型变量在运行时的可能类型。”  中年人不慌不忙。


指向性分析?Spring大臣和JVM大臣再次对视,他们明白这位中年人不会多说了。


国王盯着这位中年人,问道:“你叫什么名字?”


“小民叫Graal。”


国王心里盘算起来。


云计算时代,容器技术的出现,write once, run anywhere已经不重要了。


相反,Java确实面临着镜像大,冷启动慢的严峻挑战。


把Java代码编译成本地代码,要抛弃祖宗的基业,但可能是破局的关键。


自己作为新一代国王,坚决不能吃老本,更不能成为亡国之君,所有可能的方向都要尝试。


想到此处,国王对中年人说:“好吧Graal,寡人已经明白你的意图,现在给你一队人马,专门研究静态编译技术!Spring大臣你要密切配合!”



5尾声

几个月后,中年人推出了一个新的虚拟机,叫做GraalVM,这个VM野心极大,不仅实现了把Java编译成本地代码,还支持JavaScript, Ruby, R,Python等语言。



虽然Spring大臣不太情愿,但是国王的圣旨不可违抗,他再次与时俱进,配合GraalVM推出了SpringNative ,把Spring应用编译成了原生镜像。


SpringNative启动时间提升了50倍,并且启动即巅峰,内存占用减少了5倍。



Java在云计算时代的危机暂时度过,未来它还会遇到什么挑战呢?

- END -

1、因使用率低,谷歌翻译退出中国市场!2、不难!如果是我,我会这样做...3、Linux也能翻车?导致屏幕物理损坏4、这两个小网站助你摸鱼一整天,免翻可用!5、噩梦!安卓机最大的毒瘤,比广告还要恶心!6、用了这个库,就可以跟 Excel 说再见了7、华为监事会副主席丁耘长跑28公里后突发疾病去世,年仅53岁!
8、11 种电信设备不再实行进网许可管理,买手机可不能没有这个证!


更多精彩等待你的发现点分享点点赞点在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存