关于 Java 笨重一说

2022-05-07 23:31:10 +08:00
 ojh

今天有个帖子是说 Java 笨重、Spring 框架笨重,看完了总结了“笨重”的几点

内存占用多

这个无可厚非,毕竟运行在虚拟机上。但是之前看过一篇博客对比了 Quarkus (印象中) JIT 和 AOT 两种模式下运行内存的占用,启动初期 AOT 完胜 JIT ,但是高负载情况下两者差不多,所以我想了解下是如果同等高负载的情况下,C++/Go 这类的服务端程序的内存占用跟 Java (最新) 比差距大不大呢。

JRE 很大

这个如果在最新 Java 下面用 jlink 并且压缩一下应该 50MB (包含 JavaFX 了,不包含的没试过) 左右,一个带 JRE 的 Java 应用 50MB 应该还可以接受吧。其实我疑惑的是很多人吐槽 JRE 大,没人吐槽 NodeJS 或者 Python 大么

配置很复杂

估计指的是 Servlet 那套 web.xml 配置以及远古时代 Spring 的 context.xml ,这个我也想吐槽,不过 SpringBoot 应该缓解了这个问题

打出来的包很大

Srping/SpringBoot 为了方便开发提供了很多大而全的东西所以很大,如果你的程序就简单的接口,业务代码也很简单,什么依赖注入、切面、请求体转换、参数校验等等功能都用不到,那也没必要用 Spring 框架。顺便问一句有什么好 Java Web 框架脱离 Servlet 体系又很瘦小的

其实对于我这个 Java 菜鸡来说上面问题都不是让我郁闷的,真正让我郁闷的是 Java 为什么这么多规范!这么多规范真的好吗?

8933 次点击
所在节点    程序员
89 条回复
dcsuibian
2022-05-08 19:00:04 +08:00
3 、xml 配置复杂的问题确实存在,不过已经基本上是过去式了,主要是老项目。真要对比也得比比同时代的,Java xml 满天飞时,其它语言又是怎么做应用的。要不然拿过去比现在属实不公平。

至于规范来说,我感觉不是什么问题。毕竟软件设计 7 大原则摆在那里,都有章可循。而且现在大家做 web 基本已经形成了一种统一的模板、最佳实践,实际上是好事,减少沟通成本。

当然能打 Java 的语言也是有的,C#就是。不过成也微软、败也微软
geekvcn
2022-05-08 19:44:59 +08:00
我发现很多 Java 培训班的可能连 GraalVM 都不知道,如果他们知道的话他们口中很多 Java 的原罪根本就不成立,比如给朋友发个小工具还要发个运行时过去
l00t
2022-05-08 20:21:34 +08:00
@msg7086 你这个说法是想得很美,但实际并没什么卵用。想象中我改一下内部逻辑,保持接口不变,别人调用者就不用改。但实际上呢?你要是返回数据都不改那约等于没改,你要是返回数据改了,而人家调用者就是基于你的数据来写逻辑的呢? getID(), 开始是返回一个不会重复的 ID ,后来改成返回一个会重复的 ID ,你接口形式是没变哦,但这样的改动不得通知一下所有调用者吗?
fisherwei
2022-05-08 20:35:38 +08:00
从运维的视角看,java 最“重”的是 jar 这个东西。

CI/CD 上,java 的项目哪怕只改变一行代码,maven 出来也是一个发生了变化的 jar 文件,然而这个 jar 几乎占用一个 docker 镜像 90%以上的容量(剩下的是 jre ),导致 jar 项目 registry 总是增长的很快,也占用很多带宽。

虽然,磁盘和带宽都不缺,也不值钱。只是看起来很不爽。
thetbw
2022-05-08 20:46:43 +08:00
推荐一个 kotlin 和 ktor 这个 web 框架,基本上脱离了好多 java 这些老旧的东西,不过生产环境应该很少有用的,我机子写着玩玩会用,orm 工具可以使用 ebean
night98
2022-05-08 21:28:31 +08:00
@l00t 他的意思是比如你调用方法变更数据,现在是没有逻辑,后面比如对某几个字段需要加一个数据追踪,他直接在方法里面加逻辑就行了,你如果直接调的话就没办法这样子操作了。


@fisherwei 分层 jar 了解一下,springboot2.3 开始支持,google 的 jib 也有类似的功能,把不可变的分到上层,实际逻辑代码部分在最下层,大部分情况下都能实现秒级推送
gongquanlin
2022-05-08 21:32:23 +08:00
以前写 php 的时候简单逻辑深知直接扔到了 controller 里爽的很;
后来换了 java ,数据库改个字段,又要改 mapper.java ,又要改 mapper.xml ,又要改 domain ,如果有继承还得改 dto 、vo……麻烦的很
而且一个增删改查,又得写 service ,又得写 serviceImpl ,恶心的很

后来公司业务有多个下游请求,用到了策略工厂,用到了责任链,理解为啥一个 service 要写一个 impl ,发现存在就是合理

只能说 java 轮子又多,各种厂商对 java 的 sdk 支持又好,写业务逻辑速度很快,crud 用代码生成器效率也很高,性能比 php 好一些,部署又方便,小业务确实香

但是写 go 的时候,除了需要 cgo 的,写完之后直接 linux/windows 编译爽的很

但是吐槽一把 go 的 err 处理,要是能和 php/java 一样有统一的异常管理就好了,还得一个一个的处理 err
abcbuzhiming
2022-05-08 21:47:00 +08:00
@brust 这句话立场就不对,要知道现代编程语言的发展就是为了把很多过去认为能力不够的人拉进来编程,降低编程的门槛,如果说没有垃圾的语言只有垃圾的工程师?那以当年人月神话那会的人看现在的,在座各位都是垃圾工程师——就问有几个人敢说自己能拿打孔纸带编程的?


@Lancer777 有一说一,JVM 因为历史包袱原因,在内存使用上确实比不上新出的那些语言,否则 Oracle 也不会在那折腾 GraalVM ,现在确实是本地二进制文件的时代,中间字节码是上个时代的东西。当然,比工程化目前 java 生态圈是无敌的,这也是我为啥对转移到 Go 总是有所犹豫,还想继续观望一下 GraalVM 的原因。

@geekvcn GraalVM 目前还处于试验中,没到大规模应用的程度,其实我也馋这个,本地二进制实在太香了。就怕 Oracle 这个逼将来不愿意把这玩意给 OpenJDK ,搞收费商业化那就。。。
eason1874
2022-05-08 21:49:29 +08:00
Java 开发偏工程化,有特定流程要遵守,所以感觉是重量级编程

Python 、Javascript 、PHP 这类偏脚本,自由度大,野路子多,一个文件都能跑起来,感觉就比较轻。如果也按工程标准开发,比如用框架开发,这些语言其实也不轻
wg20080215
2022-05-08 22:16:46 +08:00
Quarkus 是一种 Java 框架,对比的应该是 SpringBoot 、Vert.x 之类的,拿来和 Java 对比是不太恰当的;另外 AOT 和 JIT 都有自己的应用场景,当下主流的云原生架构在高负载时讲究的是集群弹性,而不是单节点死扛,脱离应用场景,单点能力的对比意义不大哦。

Quarkus 的优势是和 GraalVM 的集成度很高,如果对 JPA ( Hibernate )习惯的话,用 Quarkus 可以无缝从标准 JVM 切换到 GraalVM 来获取 GraalVM 的优秀特性。

推荐视频: https://www.bilibili.com/video/BV1Cb4y1X7Rd
cheng6563
2022-05-08 22:50:35 +08:00
Java 就是典型的功能我有,但设计的非常脑残。

不支持字符串内直接引用变量,只能自己实现,导致 log4j2 神奇漏洞。
泛型拉稀导致反序列化操作非常魔法,日常增加漏洞。
日期 API 也是一坨,现在我宁愿用 DataUtil 直接操作 Date 也不想用 LocalDateTime
Future 设计拉稀,Future 甚至没有执行完毕的 Callback 。基本每个异步框架都有自己设计的“Future”,间接导致 Java 的协程难产。
不支持多行字符串导致一些操作硬是要搞成模板引擎( mybatis )。

至于为了 OO 而 OO ,这是工程化带来的负面效果。但是 Getter ,Setter 依然很蠢。
Servlet 和 JDBC 是纯历史遗留问题,但其实也不算啥问题。
Maven 的版本稳定性秒飞那些直接用 github 当依赖仓库的包管理器。
lesismal
2022-05-08 22:57:16 +08:00
@abcbuzhiming
比如农村里上茅草坑习惯了,后来进城里发现有智能马桶,很是高大上。
GraalVM 就相当于智能马桶。但即便智能马桶,它也还是屎屎相关。

go 可能像是在餐厅里吃饭,餐厅也是修得晚、软装还没完善,经常让小白们感觉斯是陋室,但这里的东西都是可以下咽的。
12101111
2022-05-08 23:21:19 +08:00
别的不提, 就算在别的变成语言中, 要想实现运行时多态, getter setter 即使没有逻辑也得有这个函数, C++的 virtual class 和 Rust 的 dyn trait 也是没法多态的时候访问字段的, C#可以用语法糖但本质上还是函数. 除非像 Javascript 或者 Python 一样把对象的字段做成字符串为 key 的 map(不过这样性能更差)
说白了 java 的笨重就体现在滥用运行时多态上, 像 C++ Rust 都是编译时多态, 很多东西都能先实例化再内联然后就优化掉了,Java 再 jit 也没法把类型已经擦除掉类型的对象的函数内联优化掉
我读过不少 chromium 的代码, 写的跟 java 一样罗嗦,但是调试的时候发现代码几乎都是 inline 的, 带上调试符号, 汇编也很难和代码对的上, jvm 再厉害也不可能做成这样
不过 v8 的 gc 也不比 jvm 厉害, 所以内存占用也不小, 但是运行速度比 jvm 快多了. chromium 这好几千万行的项目要是 java 写的, 恐怕就没有现在前端那一堆东西了, 浏览器能慢成牛
FrankHB
2022-05-08 23:25:57 +08:00
有个这里都没提的:冷启动性能。
一般人会遇到的竞品里怕是没有一个是能比 Java 的实现更加卡翔的。这直接导致拿 Java 写单进程小工具看起来就是没事找抽,直接自绝于一大坨应用领域。

@msg7086 @lanlanye 大部分人眼中的 getter/setter 的问题和提到的没多少关系。很多用户吐槽 Java 这里垃圾,是因为他们想要类似 C#的 property 代替,而 Java 愣是不给。不管用不用 property 代替,都不影响你们这里提的东西。
基于一些深层次的理论问题,我不认为 Java 这里的设计是错的,也不是只有 Java 这样(至少 C++也不给什么劳什子 property 面子)。(具体一点,即便不考虑η-equivalence 这样的异端,这种基于标识符的语法变换缺乏 hygiene 而最终导致语法扩展无法从源码直接推理就够眼烦的了。)不过 Java 这种连 macro 都没的八辈子都别想 call by name 的语言自然就不用纠结这么多,糊 JLS 跟 JEP 的那些大概人也许只是觉得让这种雕虫小技还不如 IDE 帮忙糊代码愉悦罢了。
至于为什么非得 getter/setter 而不是直接拿字段代替,这很大程度上就是用户之间的内部矛盾。
dqzcwxb
2022-05-08 23:44:08 +08:00
@eason1874 #69 很多人就是把工程化的毛病硬套给语言,搞的好像别的语言工程化之后就没有这样的毛病一样
没有理解为什么需要这样做只是单纯的觉得这样做麻烦繁琐老旧,这种不是在创新而是反智
dqzcwxb
2022-05-08 23:59:55 +08:00
@chocotan #48 通篇看下来,大部人的对 java 的认知还停留在 2013 年的 java8 甚至这里还有一些停留在 java8 以前
能够了解 java8 有什么更是少之又少 stream lambda optional localdatetime completablefuture 等等更是完全不懂
后面还有 java11 的 zgc 13 的文本块 14 的 instanceof 等等等等他们更别提能够了解十之一二

在这里给各位通知一下,最新的 jdk 版本是 2022/03/22 发布的 jdk18,而下一个 jdk19 版本正在开发中目前预告的特性中包含协程,请大家务必跟上新时代不要做旧时代守门人
Lancer777
2022-05-09 00:29:18 +08:00
@abcbuzhiming GraalVM 我已经在生产环境上使用了很久了,并没有什么太大问题,主要问题还是在于 Java 生态圈对于这玩意的支持还是太慢了,Quarkus 的上手成本太高,Spring Native 出来的太晚,并且编译速度太慢,还是要等一段时间才能愉快的使用。
Lancer777
2022-05-09 00:32:29 +08:00
@cheng6563 Java8 的时间类可是借鉴 JODA Time 的,你说设计的一坨?还有多行字符串在新版的 JDK 已经支持了,get ,set 在 OO 语言里面可不是 Java 独有,.net 也是这么写的。协程马上就来了,还有 4 个月,预计 21 就可以出稳定版啊。
msg7086
2022-05-09 02:21:18 +08:00
@dqzcwxb 笑死,我们团队刚刚升级到 JDK8 ,之前一大堆项目都在 7 ,还在龟速移植中。上个月刚接手一个 JDK1.6 上来的项目,连泛型都几乎没有,那叫一个酸爽。不知道等我退休的时候能不能用上 17 。(摊手
cheng6563
2022-05-09 10:47:50 +08:00
@FrankHB 冷启动问题就是 jar 包设计的太蠢了,Android 上的 dex 包就没这问题。
@Lancer777 LocalDateTime 和 Date 的转换蠢到家了,甚至 java.util.Datejava.sql.Date 也不完美兼容。导致每个项目都要写个 DateUtils ,我还不如直接统一用 DateUtils 操作 Date 了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/851477

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX