1000万云上开发者,全栈云产品0元试用:点击「链接」免费试用,即刻开启云上实践之旅!
本文就Java真的老了吗展开讲述,诠释了作者作为一名Java开发者的所思所感。
作者 | 傅健丰(健风)
来源 | 阿里开发者公众号
最近抽空看了Go、Rust等一些语言的新版本特性,还有云原生的一些基础设施(Docker,Kubernetes,ServiceMesh,Dapr,Serverless),有点感慨Go真的是云原生的“一等公民”,像是启动速度快、依赖少、内存占用少、Goroutine 并发等无一不是击中Java的软肋。然后突发奇想在Google上搜了下“Java老矣”,能搜出520,000条结果。不禁想问:Java真的老了吗?
自1995年出生以来,Java已经有27年历史了,曾经的风吹雨打风吹去,一些优秀的设计在今天看来似乎并不那么重要甚至过时了。比方说:
另一个广为诟病的是Java的资源占用问题,这主要包含两方面:静态的程序大小和动态的内存占用。
Java的启动时间也是一大心病,主要原因在于启动时虚拟机初始化和大量类加载的时间开销(当然还有一个罪魁祸首是Spring的bean初始化,我之前写了个异步初始化Spring Bean的starter rhino-boot-turbo,把串行改并行启动速度会快很多)。本身镜像体积大,拉取时间就长,再加上分钟级的启动时间,部署应用就更显得慢了。传统的企业应用更看重长时间运行的稳定性,重启和发布频率相对较低,对启动时间相对没那么敏感,然而对于需要快速迭代、水平扩展的微服务应用而言,更快的的启动速度就意味着更高的交付效率和更加快速的回滚。尤其是对于Serverless应用或函数,冷启动速度至关重要,之前看AWS Lambda函数允许最多运行5分钟,很难想象还要花一分钟时间先启动。
云原生的潮流滚滚而来,Java的这些缺陷在要求快速交付的大环境下显得格格不入,难怪Java与Go、Rust等原生语言相比,会显得“落寞”了。
作为一个Java程序员,肯定想问,Java还有机会吗?想起有位长者说过:一个人的命运啊,当然要靠自我的奋斗,另一方面,也要考虑历史的进程。我想把它改成:Java的命运啊,当然要靠自身的努力,另一方面,也要考虑队友们给不给力。
我们的大部分系统都还跑在Java 8之上,因此作为开发同学对Java 8也是最熟悉的。从Java 9开始,JDK的版本号堪比版本狂魔Chrome涨得飞快,除去开发者能够肉眼感知的语法和API的变动(Productivity)之外,Java也在性能(Performance)上一直努力。
我捋了一下OpenJDK官网[1]从Java 9开始的JEP列表,按照个人理解列出了关键的一些特性。
在数次delay之后,Java 9终于正式引入了Java平台模块系统(JPMS),项目代号Jigsaw。在这之前,Java以package对代码进行组织,再将package和资源打成Jar包,模块则在package的概念上将多个逻辑上、功能上相关的包以及相关的资源文件封装成模块。关于模块的详细介绍,可以参考下官方的介绍文档:Understanding Java 9 Modules[2]。
此前,Java Runtime的庞大臃肿一直为人诟病(一个rt.jar就有60多M,整个JRE环境可以达到上百M),瘦身正是Project Jigsaw的目标[3]之一。此外,还有Jar Hell、安全性等等问题。
不过模块化看着很好,也隐藏着陷阱:
对于新的项目,使用模块构建似乎是值得的,但现状是,大多数开发者会忽略模块系统,尤其是对于已经运行了多年的大型项目,改造的成本令人望而却步。我猜测肯定会有人吐槽类似的问题:
搜了一下,似乎国外网友也有一样的疑惑[7]。不过,我认为让程序员可以定义应用程序的模块是什么,它们将如何被其他模块使用,以及它们依赖于哪些其他模块,这些事情还是有必要做的。
当然Java9除了模块化之外,还有一些其他特性也值得关注:
关于 JVMCI 多介绍一些。相比用 C 或 C++ 编写的现有编译器(说的就是你,C2),用Java写编译器更容易维护和改进。JVMCI的API 提供了访问 JVM 结构、安装编译代码和插入 JVM 编译系统的机制,后面讲到的Graal正是基于JVMCI。
JVMCIJIT编译器与JVM的交互可以分为如下三个方面。
响应编译请求;
获取编译所需的元数据(如类、方法、字段)和反映程序执行状态的profile;
将生成的二进制码部署至代码缓存(code cache)里。
即时编译器通过这三个功能组成了一个响应编译请求、获取编译所需的数据,完成编译并部署的完整编译周期。
传统情况下,即时编译器是与Java虚拟机紧耦合的。也就是说,对即时编译器的更改需要重新编译整个Java虚拟机。这对于开发相对活跃的Graal来说显然是不可接受的。
为了让Java虚拟机与Graal解耦合,引入 JVMCI 将上述三个功能抽象成一个Java层面的接口。这样一来,在Graal所依赖的JVMCI版本不变的情况下,我们仅需要替换Graal编译器相关的jar包(Java 9以后的jmod文件),便可完成对Graal的升级。
其实JVMCI接口就长这样:
public interface JVMCICompiler {
/**
* Services a compilation request. This object should compile the method to machine code and
* install it in the code cache if the compilation is successful.
*/
CompilationRequestResult compileMethod(CompilationRequest request);
}
剩余60%,完整内容请点击下方链接查看:
一些杂想:Java老矣,尚能饭否?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。