尤其是一些客户端开发的,java8又大(无法用jlink剪裁,runtime是java 11+做出来的几倍大),各种特性又少,无论是java core还是javafx,都在最新几个版本中大幅提升性能和特性,为什么还有那么多人执着于java 8?
2018年我有一大部分工作都在和Java 9 作斗争!Java 9是2017年9月发布的,而我们一直到2018年9月——花了整整一年的时间——才切换到Java 9,又花了三个月的时间切换到Java 11。
反观JetBrains,似乎花了两年多才把runtime升级到11(假设他们是从Java 9一发布就升了),我们和JB的代码规模差不多,都是百万级别的,现在你应该对升级这事的周期有一个基本的认识了吧?
总结一下,就是Java 9各种奇怪的改变+业界长久积累的库中的瞎JB用法导致了大部分项目被迫停在Java 8上。我强烈建议把题目改成「为什么还有那么多人被迫使用Java 8」,因为,这真的是客观原因啊。
我举几个栗子让你们看看迁Java 9/11这件事情有多蛋疼,算是给想迁移的你们提前打个预防针。
Java 9之前,Java的版本号用的是这个标准,也就是我们常见的1.8.0_213这种字符串。 Java 9之后,大家一拍大腿,反正已经做了这么多改变,不差这一个!来人啊!给我把这个版本号字符串换掉!于是有了JEP223,一个山寨版的语义化版本号,从此以后,版本号大概长这个样子:9.0.0.4。平心而论,这个变更是非常必要的,但是一众依赖以前的版本号字符串的库就都哭了……谁能想到你丫的连这种东西都变啊。
(据说当年还有人提议以后Java的版本号跟业界保持一致,用18.1/19.1之类的年份+次序命名 ,后来就没声音了,应该是被打死了。)
那些广为人知的大库还好说,改的还算及时,一些小作坊生产的三无库就惨了,一调用就给你丢个Illegal version number 9.0.0.4出来, 还找不到人修,来来来你说咋办?
Java 8之前对反射没有限制,只要setAccessible(true),你连JVM的底裤都可以掀掉。我们都知道,一旦给用户自由,用户就会瞎JB用。大家都知道JVM初始化的时候传进来的环境变量是不可变的,存在ProcessEnvironment的一个不可变Map里。但是没关系,我有反射啊……
其他的栗子还包括,通过反射调用各种私有的API……在你升级之前,你永远不知道有多少地方在用这种鬼鬼祟祟的操作……升级就好像你面前的一条康庄大道,你开开心心地踏上去准备走,咚!一个地雷炸了!piaji!你掉坑里了!二十米的路你走了三个月!黑着脸从坑里爬出来,瞅瞅前面……这特么还有多少个地雷在等着我啊……在爆炸之前你永远不知道到底有多少库在用反射偷偷摸摸调私有API,我管它叫薛定谔的反射
还有最常用的一个操作叫做defineClass,用来把魔改后的字节码注入ClassLoader。ClassLoader的这个方法是protected的,没关系,我们有反射啊……另外一些小伙伴直接用反射调用Unsafe.defineClass——看名字你就知道有多不安全,Java 11之后这个方法直接被干掉了。
能用到这些方法的库通常都是大厂生产的有售后的库,所以通常都能得到很好的解决。但是紧接着问题就来了——你把一个库从2011年的版本直接升到了2018年的版本,你心里慌不慌?
更别提有些小作坊的库偷偷摸摸地从裤裆里掏出来一个Unsafe.defineClas
在升Java 9成功之后,怀抱着升级成功的窃喜,我们又趁热打铁想升Java 10。然后碰到了IDEA的一个bug:IDEA错误地理解了一个还未生效的草案JEP182,编译器给出了不正确的结果,我花了一上午时间调试IDEA的源代码才发现是IDEA的锅。IDEA尚且如此,其他项目碰到兼容性问题,真的只是时间问题。
业界的很多工具不支持Java 9,最广为人知的应该是FindBugs了。还好,它还算后继有人,SpotBugs挑起了它的大梁,那些小作坊库可就惨了,过去的十年是Java生态系统迅猛发展的十年,你的项目只要沾到一点“在自己的代码里瞎JB使用Java 8/断言自己使用的是Java 8”的库,可能就要花上几天时间去调试、去尝试解决。
最后,最重要的一点是,我们的代码是有严格的自动化测试覆盖的,所以我们在升级之后能非常有底气地说我们升级成功了!对于没有测试覆盖的祖传代码,你升级完事,跑一下,似乎没问题,但是真的没问题么?去问老天爷吧……没有完善的测试覆盖的项目请勿轻易尝试。
其实升级不是什么非常困难的事情,主要是费时费力,收益可能却没有那么明显。对于一个成熟的公司来说,代码只是辅助业务的手段,而非目的。如果没有十分的利益保证,别说升级,连bug都是可以不修的。就这样。
网友评论