百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

一些杂想Java老矣,尚能饭否

toyiye 2024-06-21 12:27 12 浏览 0 评论

1000万云上开发者,全栈云产品0元试用:点击「链接」免费试用,即刻开启云上实践之旅!


本文就Java真的老了吗展开讲述,诠释了作者作为一名Java开发者的所思所感。

作者 | 傅健丰(健风)

来源 | 阿里开发者公众号


最近抽空看了Go、Rust等一些语言的新版本特性,还有云原生的一些基础设施(Docker,Kubernetes,ServiceMesh,Dapr,Serverless),有点感慨Go真的是云原生的“一等公民”,像是启动速度快、依赖少、内存占用少、Goroutine 并发等无一不是击中Java的软肋。然后突发奇想在Google上搜了下“Java老矣”,能搜出520,000条结果。不禁想问:Java真的老了吗?


“落寞”的Java

自1995年出生以来,Java已经有27年历史了,曾经的风吹雨打风吹去,一些优秀的设计在今天看来似乎并不那么重要甚至过时了。比方说:

  • "Write Once, Run Everywhere"的平台无关特性在当年确实是真香,但现在这种部署的便利性已经完全可以交由Docker为代表的的容器提供了(从某种意义上说,JVM也是字节码的容器),而且做得更好,可以将整个运行环境进行打包。想想Docker的口号也是:"Build Once, Run Anywhere"。
  • Java 总体上是面向大规模、长时间运行的服务端应用而设计的。在语法层面,Java+Spring框架写出的代码一致性很高;在运行期,有JIT编译、GC等组件保障应用稳定可靠。这些特性对于企业级应用十分关键,曾经是Java最大的优势之一。但在微服务化甚至Serverless化的部署形态下,有了高可用的服务集群,也无须追求单个服务要 7×24 小时不可间断地运行,它们随时可以中断和更新,Java的这一优势无形中被削弱了。

另一个广为诟病的是Java的资源占用问题,这主要包含两方面:静态的程序大小和动态的内存占用。

  • 不管多大的应用,都要随身带一个臃肿的JRE环境(这里先不讨论模块化改造),加上各种复杂的Jar包依赖,看了下我们团队的每个Java应用的容器镜像大小都轻松上G。
  • 应用的运行期内存占用居高不下,这个是Java天生的缺陷,很难克服。

Java的启动时间也是一大心病,主要原因在于启动时虚拟机初始化和大量类加载的时间开销(当然还有一个罪魁祸首是Spring的bean初始化,我之前写了个异步初始化Spring Bean的starter rhino-boot-turbo,把串行改并行启动速度会快很多)。本身镜像体积大,拉取时间就长,再加上分钟级的启动时间,部署应用就更显得慢了。传统的企业应用更看重长时间运行的稳定性,重启和发布频率相对较低,对启动时间相对没那么敏感,然而对于需要快速迭代、水平扩展的微服务应用而言,更快的的启动速度就意味着更高的交付效率和更加快速的回滚。尤其是对于Serverless应用或函数,冷启动速度至关重要,之前看AWS Lambda函数允许最多运行5分钟,很难想象还要花一分钟时间先启动。

云原生的潮流滚滚而来,Java的这些缺陷在要求快速交付的大环境下显得格格不入,难怪Java与Go、Rust等原生语言相比,会显得“落寞”了。

作为一个Java程序员,肯定想问,Java还有机会吗?想起有位长者说过:一个人的命运啊,当然要靠自我的奋斗,另一方面,也要考虑历史的进程。我想把它改成:Java的命运啊,当然要靠自身的努力,另一方面,也要考虑队友们给不给力。


JDK的演进

我们的大部分系统都还跑在Java 8之上,因此作为开发同学对Java 8也是最熟悉的。从Java 9开始,JDK的版本号堪比版本狂魔Chrome涨得飞快,除去开发者能够肉眼感知的语法和API的变动(Productivity)之外,Java也在性能(Performance)上一直努力。

我捋了一下OpenJDK官网[1]从Java 9开始的JEP列表,按照个人理解列出了关键的一些特性。

Java 9:难产的模块化

在数次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、安全性等等问题。

不过模块化看着很好,也隐藏着陷阱:

  • 不可忽视的改造成本
  • 虽然提供了未命名模块和自动模块,Oracle也提供了迁移指南和工具[4]供参考,但改造的成本依旧很大,特别是梳理模块之间的依赖关系,较为繁琐。
  • 小心使用内部API
  • 模块化的最大卖点之一是强大的封装性,它确保非public类以及非导出包中的类无法从模块外部访问。但在这之前,jar包中类的访问是没有限制的(即使是private也可以通过反射访问)。比如JDK中的大部分com.sun.*sun.*包是内部无法访问的,但这之前被用得很多(出于性能/向前兼容等等原因),虽然Oracle的建议是不要使用这些类:Why Developers Should Not Write Programs That Call 'sun' Packages[5]。
  • 小心使用内部JAR
  • 像lib/rt.jar和lib/tools.jar等内部 JAR不能再访问了。不过正常来说,应该只有IDE或类似工具会直接依赖?
  • 小心使用JAR中的资源
  • 一些API会在运行期获取JAR中的资源文件(例如通过ClassLoader.getSystemResource),在Java9之前会拿到 jar:file:<path-to-jar>!<path-to-file-in-jar>这类格式的URL Schema,而Java9之后则变成了 jrt:/<module-name>/<path-to-file-in-module>
  • 其他一些问题[6]


对于新的项目,使用模块构建似乎是值得的,但现状是,大多数开发者会忽略模块系统,尤其是对于已经运行了多年的大型项目,改造的成本令人望而却步。我猜测肯定会有人吐槽类似的问题:

  • 我已经分成不同jar包了,我感觉这样就可以了,有必要更进一步吗?
  • 我又不是开发中间件和框架的,我开发业务应用,为什么要关心这些?
  • 就算我有二方包要开放出去,为二方包维护模块定义似乎也带不来多少收益?
  • 该如何分离每个模块,基于什么原则?就跟DDD一样,我知道这东西很美好,有最佳实践可以参考吗?

搜了一下,似乎国外网友也有一样的疑惑[7]。不过,我认为让程序员可以定义应用程序的模块是什么,它们将如何被其他模块使用,以及它们依赖于哪些其他模块,这些事情还是有必要做的。

当然Java9除了模块化之外,还有一些其他特性也值得关注:

  • compact strings[8],通过对底层存储的优化来减少String的内存占用。String对象往往是堆内存的大头(通常来说可以达到25%),compact string可以减少最多一倍的内存占用;
  • AOT编译[9],一个实验性的AOT编译工具jaotc[10]。它借助了Graal编译器,将所输入的Java类文件转换为机器码,并存放至生成的动态共享库之中。jaotc的一大应用便是编译java.base module(也就是模块化后Java核心类库中最为基础的类)。这些类很有可能会被应用程序所调用,但调用频率未必高到能够触发即时编译。
  • JVMCI[11]( JVM 编译器接口),另一个experimental的编译特性。用Java写Java编译器,Java也可以说我能自举了!


关于 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老矣,尚能饭否?


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码