关于 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 为什么这么多规范!这么多规范真的好吗?

8426 次点击
所在节点    程序员
89 条回复
ikas
2022-05-07 23:49:10 +08:00
本来想一一回复的..发现没有意义..

还是多学点吧
thinkershare
2022-05-07 23:51:59 +08:00
Java 整个体系没啥大问题, 除了啰嗦了点. 否则也不会成为如今后端的 TOP 1 了, 虽然有历史的进程原因.
1. Servlet 规范是没法抛弃的, 这个本质上就是整个 JAVA 生态的原初理念
2. 字段不应该直接暴露, 这个和有无逻辑毫无关系, 暴露细节违反了面向对象最基础封装特性, 这个几乎没有争议
3. 面向接口编程没啥问题, Java 一些解决方案的复杂化是因为大家都过渡追求复用, 然后过度抽象. 如果你确定一个东西不会更改, 你完全就可以直接 new, 你看你的代码是不是到处都在直接构造 String 这些基本类型. 最佳实践都是人们踩过的坑后慢慢总结出来的, 因此公司项目还是要以规范性为主, 因为你需要和其它人协作, 多人协作一致性是最重要的一条原则.
ojh
2022-05-07 23:59:01 +08:00
@ikas 大佬请指点下迷津,特别 Getter 、Setter 方法你有什么看法
geekvcn
2022-05-07 23:59:06 +08:00
培训班出来的半吊子太多了,把自己的缺点说成语言的缺点。
Leviathann
2022-05-08 00:01:17 +08:00
对外暴露的是 property
不一定需要对应一个 field
而具体有没有对应一个 field 外界不需要知道
连 js 都有 getter setter 了
ojh
2022-05-08 00:01:54 +08:00
@thinkershare 但是这些好像就唯独 Java 特有,其他后端语言也没这么麻烦
golangLover
2022-05-08 00:04:44 +08:00
@ojh 学一下 lombok
geekvcn
2022-05-08 00:07:15 +08:00
第一点内存占用多,你为什么不用 C++写项目?有人逼着你用 Java 写? Java 跑在 JVM 上,天生就多了 JVM 的内存占用,真内存敏感还非要用真的是你自己的问题。
JRE 很大,如果你是上世纪的电脑我还能理解,如今的电脑 JRE 那大小算个屁。
配置很复杂,依赖很多,打出来的包很大 这两条就更离谱了?你是把框架的问题算到 Java 头上了,你不满意现有轮子,自己造轮子不就行了,没人逼你用这些框架吧?
Leviathann
2022-05-08 00:07:51 +08:00
大部分 springer 都把对象当成是函数的命名空间或者数据的载体在用,而不是真把它当成一个状态与行为的聚合体
实际上就是在写假装是面向对象的过程式代码
ojh
2022-05-08 00:10:08 +08:00
@geekvcn 大佬莫激动,我是总结另外一个帖子,然后再发表了一下自己认为的解决方案,这个是讨论帖子不是吐槽帖😂
ojh
2022-05-08 00:11:24 +08:00
@Leviathann 可能我对 Java 的 field 和 property 欠缺理解,要去补补了
yesterdaysun
2022-05-08 00:31:44 +08:00
我觉得相比老的 j2ee, Spring/SpringBoot 已经算轻的了, 虽然离云原生的标准还差了不少, 但是毕竟也是有其他优势的, 就是生态好, 工具 /社区丰富, 也隐藏了一些复杂的底层细节, 所谓"笨重"应该不是首要考虑的问题

此外, Getter/Setter 我觉得是必要的, 如果是真纯数据类型, 已经有 record 类了, 如果要加上一些行为的话, 隐藏在 Getter/Setter 后面是最方便自然的了, 如果只是怕麻烦, 可以用 lombok, 很方便

IService/ServiceImpl 这个应该是如果是接口的话, 底层就会用 JDK 动态代理实现, 如果是有一个 Service 的话, 用的 CGLIB, 据说性能稍微差一点, 反正我的话, 如果接口有多个实现, 就用接口, 如果只是单个实现, 就不要接口

你说一个请求要好几层的话, 这个和接口什么的没有关系, 是设计的问题, 要看你的项目架构怎么设计和定义的了, 一般都得分个请求层 /服务层 /数据层之类的, 如果说 3 层都闲多, 要目你的项目太简单是真不需要, 要么就是还没遇到合在一起遇到的麻烦事.

如果说的是单 Service 层有好几层, 那要看具体情况了, 如果只是单单说是公司规定, 全是模版代码, 我建议如果不能说服老大, 那自己做一个模版代码生成器会方便很多
secondwtq
2022-05-08 00:35:57 +08:00
内存占用和 JIT 、AOT 是没关系的,主要是 Tracing GC 的问题。Tracing GC 就意味着任一时刻内存中必然有一部分数据是“无用”的,造成内存空间的“浪费”。
其他 Tracing GC 的语言也一样,并且 GC 调优有时候还需要用更多的“无用”内存占用换取 GC 更少触发。
其实不用 Tracing GC 也会有其他问题,比如用了对象池 /内存池。在这些情况下,内核看到的内存占用其实都不能代表应用程序的“真实”内存占用,但是这些“没用”的内存又确确实实被占着。
techstay
2022-05-08 01:04:35 +08:00
getter 和 setter 这属于历史遗留问题,当初不算什么问题,现在各种语言说白了也只是用语法糖包装一下。各种规范也没啥吧,Python 不是也是一堆 PEP
WebKit
2022-05-08 01:11:05 +08:00
要不试试 kotlin 的 ktor
stevefan1999
2022-05-08 01:26:38 +08:00
billlee
2022-05-08 01:49:22 +08:00
java 的内存问题不单是 tracing gc 带来的占用内存多的问题,还有个更复杂的问题是对象类型的变量是引用,无法嵌套对象。这个不但有内存使用量的开销,还有因为内存布局无法控制可能带来性能损耗。

有些对内存局部性敏感的算法用 java 写出来就是要比 C++ 慢,有时为了优化性能,必须放弃面向对象的写法,把对象数组改成每个属性拆出来单独存数组, 写出来的代码就和 matlab 差不多。

拿 C++ 的话来说,就是 java 的面向对象抽象不是零开销的。
SeaTac
2022-05-08 02:41:16 +08:00
Getter/setter 这个问题,看看 lombok ?
pengtdyd
2022-05-08 03:45:47 +08:00
那么问题来了,什么是轻?汇编够轻了吧!!!
muhuan
2022-05-08 07:19:25 +08:00

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

https://www.v2ex.com/t/851477

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

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

© 2021 V2EX