果然吃内存,一个简单的 Java 程序就占用了 250M 内存

2024-07-08 20:36:54 +08:00
 karottc

之前一直在用 Java 写 企业级代码,并没有很在意 java 的内存问题,比如多个/少个一两百兆就没关心。

平时用 java 写的直接运行就结束的代码,基本都是本地电脑运行,也没有发现内存问题。

直到最近,用 java 写了一个简单的程序,运行在我的 1C1G 的腾讯云机器上,才发现 java 确实内存大户。

程序的功能为:

  1. 每 10 分钟抓取某个链接的数据
  2. 抓取到的内容和 mysql 里面已有的内容作对比
  3. 存在就更新,不存在就插入到 mysql 中
  4. 每天早上 10 点发送一个企业微信通知

这就是这个程序的所有功能,由于用到了定时任务和操作 mysql, 所以我第一个版直接用了 springboot ,平时工作也用整起来快。 用到的库为:okhttp + gson + mybaits + jdbc + logback

程序运行稳定之后内存占用:250M

这个简单的功能这个内存占用实在是太大了。

然后我觉得可能是 springboot 的原因,所以我写了第二版: 用了 okhttp + gson + mybatis + jdbc 去掉了框架和 logback, 直接用 print 输出 log , 定时任务也直接用了 while(true) + sleep 来实现。

这版程序稳定运行之后内存占用:90M

上面两版没有加任何优化参数,就是 java -jar xxx.jar 运行。 java 版本:java21


java21 了,还是这个内存表现,失望啊。

21020 次点击
所在节点    Java
125 条回复
yazinnnn0
2024-07-08 22:59:56 +08:00
设置下堆内存

不过 jvm 运行时就这么大, 先天就会吃掉一些

你真的在乎的话可以换 quarkus+graalvm, 大概能控制在 20M 左右

要么就换语言吧, 用 rust 或者 go

不过我建议你用 crontab, 跑完任务就 return 了, 不用管占用了多少内存
jry
2024-07-08 23:07:17 +08:00
中小项目我站 PHP ,维护太方便了,本地就起一个 PHP-FPM 占用 50MB 内存,项目随便放多少个都不影响,维护访问才会占用一下内存访问完立刻就释放了。要是维护很多 java 就麻烦的不行,要各个项目常驻内存,启动就得老半天。
0xD800
2024-07-08 23:07:56 +08:00
我用 java 写的一个 ddns ,根本不关注内存,crontab 一分钟跑一次
0xD800
2024-07-08 23:09:11 +08:00
我记得新版的 GC 是对大内存友好,对小内存好像不怎么友好,你试试 jdk8 用老的 GC 看看
Huelse
2024-07-08 23:12:00 +08:00
话虽如此,但在大规模 IO 应用上 java 还是唯一选择
powerman
2024-07-08 23:16:02 +08:00
@HFX3389 这个都不知道死了 多久了,上学那会 mtk 的山寨手机 估计还有在用,现在几乎绝迹了
jackmod
2024-07-08 23:25:45 +08:00
小工具应用我甚至已经决定放弃 Python 了,正在抓紧时间掌握 golang
dcsuibian
2024-07-08 23:30:27 +08:00
不是 java 内存大了,是你内存小了。我个人 2c4g 的腾讯云轻量,根本没想过内存占用
arloor
2024-07-08 23:35:35 +08:00
@yazinnnn0 支持换 rust 或者 go 。今天刚用 rust 写了个小工具提效,同事说竟然是用 rust 写的,无形中秀了一把哈哈。
cocalrush
2024-07-08 23:46:56 +08:00
你继续跑 1k 个链接任务,会发现仍然是这么大的内存
Donaldo
2024-07-09 01:36:46 +08:00
说实话,你这个需求真没必要用 Java ,我估计在这个场景大部分内存都被 runtime 吃掉了,真正业务逻辑吃掉的内存少之又少。
labdum
2024-07-09 04:31:04 +08:00
主要是最低开销大吧,但是上限对比之下还好

https://pkolaczk.github.io/memory-consumption-of-async/

<amp-youtube data-videoid="WjKQQAFwrR4" layout="responsive" width="480" height="270"></amp-youtube>?si=-OluA5cgtfgahdWp
kuanat
2024-07-09 08:04:23 +08:00
这一套跑起来要多少内存属于常识性问题,不是说那遇到过才知道的。另外企业级代码也要有企业级的运行环境做支撑啊,没有配套的环境谈什么企业级。

不如反过来你尝试回答这样一个问题,这个需求你还能用别的方式熟练的完成么?不能的话那你没得选,能的话说明决策有问题。

比如这个需求 mysql 换成 sqlite 不行么,裸写 sql 不行么,甚至说存自定义格式不行么?既然都是 http 请求加 json 解析,换成 Python 不行么,如果 python 不方便部署,换成 go 之类的不行么。

特别当你知道运行环境就是 1c1g 的时候,更应该考虑这些变通的手段啊。如果换成我的话这个需求我连 self host 都不会用,免费的 cf worker 比你的小主机可用性高太多了。也许你都没考虑过长期维护的事情。这种需求要的是省心,但你现在的选型和实施都没自动化的考量,配置一个简单的 cd/ci 之后这个差距会更大。

说这么多其实是想表达,不要把完成需求仅仅局限在写代码的层面上,当成项目来管理运营会更容易做出整体上更合理的决策。
Fule
2024-07-09 08:36:41 +08:00
纯粹说明一下个人对 @labdum 引用的那个文章的看法。

那个文章的作者大概不是对他列举的每一门语言都足够了解。我对其它语言了解不多,但是一如那个文章回帖里说的,C#的写法不太行,而且都 .NET 6.0 的测试环境了,创建如此大量 Task ,要不要考虑下 ValueTask 的可行性。我相信列举的其它语言的写法也有类似问题,所以那篇文章的参考价值是:一个某某语言的初级程序员在不充分了解语言特性和机制的情况下写出的未优化的代码的内存开销有多遭。
selca
2024-07-09 08:42:18 +08:00
graalvm 试试
luzemin
2024-07-09 08:44:15 +08:00
@angrylid 你好,佳琦
kandaakihito
2024-07-09 08:52:06 +08:00
是这样的,而且 spring 那套脚手架即使是很熟练了起手也得搭半天
wysnxzm
2024-07-09 09:10:37 +08:00
java 不设置内存大小默认使用物理机 1/4 内存与代码无关,按理说都用 jdk21 了不至于连这个都不知道啊
xubeiyou
2024-07-09 09:12:35 +08:00
。。。用 Java 了-- 肯定耗内存啊 这个东西 用地方越小 越不值当
Blanke
2024-07-09 09:14:57 +08:00
都用 java 了还在乎啥内存

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

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

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

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

© 2021 V2EX