之前一直在用 Java 写 企业级代码,并没有很在意 java 的内存问题,比如多个/少个一两百兆就没关心。
平时用 java 写的直接运行就结束的代码,基本都是本地电脑运行,也没有发现内存问题。
直到最近,用 java 写了一个简单的程序,运行在我的 1C1G 的腾讯云机器上,才发现 java 确实内存大户。
程序的功能为:
这就是这个程序的所有功能,由于用到了定时任务和操作 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 了,还是这个内存表现,失望啊。
我用python 写了核心功能,内存占用 20M。
又用quarkus-graalvm 完全1:1重构了一遍,内存占用50M。 详见这个帖子 https://www.v2ex.com/t/1057699
![]() |
1
medivh 61 天前 via iPhone
试试 openj9
|
![]() |
2
powerman 61 天前
加钱吧,Java 整个生态来讲,早就不是设计之初,应用于嵌入式设备 微波炉 洗衣机 等玩意的语言了,你要是从头撸起来,httpclient + 自己手撸一个 json 解析器 + jdbc template ,其实内存也用不了多少
|
![]() |
3
powerman 61 天前
而且 Java 目标就是 作为一个企业级的后台开发生态工具了,早就不适合 嵌入式 等资源受限的场景
|
![]() |
4
cmdOptionKana 61 天前
没有完美的语言,总不能没有短板吧,要是 Java 那么完美,其他语言也没生存空间了。
|
![]() |
5
angrylid 61 天前 ![]() 哪里多了,这么多年一直都是这个占用,不要睁着眼睛乱说,write once run anywhere 很难的。
|
![]() |
6
povsister 61 天前
只能说 java 是这样的,不然也不会云原生时代被 go 按脑袋了。
|
![]() |
7
cdlnls 61 天前
你看看 jmap -heap 内存占用多少,然后根据实际占用情况调整 Xmx
|
8
Ayanokouji 61 天前
既然这么在意内存,为何不上 graalvm 试试呢
|
9
xuhengjs 61 天前
jvm 的内存占用,小项目确实不划算
|
![]() |
11
suyuyu 61 天前 ![]() 那么我可要宣布了。PHP 是世界上最好的语言
|
![]() |
13
zhouxiaoben 61 天前
确实,我的个人网站换了 nuxt + go ,内存占用也少很多
|
14
Donahue 61 天前
那我可要宣布了 go 语言是世界上最好的语言。
非常适合写这种工具/脚本类的小应用 |
![]() |
15
chendy 61 天前 ![]() 嫌大就加参数限制最大堆呗,默认最大堆四分之一物理内存肯定大啊
我在服务器上跑的一个小定时任务,spring-boot 弄的,xmx32m 一样跑 |
![]() |
16
Rorysky 61 天前
估计 python 差不多
|
![]() |
17
ns09005264 61 天前
换个语言吧,我从没想过用 java 写小工具。
再说学习新的语言对编程技术有一定的提升。 |
![]() |
18
Vegetable 61 天前
这也是我一直诟病的,JAVA 写习惯了的开发,起手就是 Spring Boot ,嘴里反复念叨着内存不值钱啊,依赖注入啊什么的。
曾经因为我电脑只有 jdk 没有 ide ,问一个朋友,你知道怎么在命令行执行一个.java 文件吗?他说不知道。 |
![]() |
19
8620 61 天前
加入 C 的怀抱吧,内存管理编码者自己来~
|
![]() |
20
diagnostics 61 天前
@Vegetable 说明你朋友培训班出来的,学 Java 课,起码作业会让你用 javac
|
21
yazinnnn0 61 天前 ![]() 设置下堆内存
不过 jvm 运行时就这么大, 先天就会吃掉一些 你真的在乎的话可以换 quarkus+graalvm, 大概能控制在 20M 左右 要么就换语言吧, 用 rust 或者 go 不过我建议你用 crontab, 跑完任务就 return 了, 不用管占用了多少内存 |
![]() |
22
jry 61 天前
中小项目我站 PHP ,维护太方便了,本地就起一个 PHP-FPM 占用 50MB 内存,项目随便放多少个都不影响,维护访问才会占用一下内存访问完立刻就释放了。要是维护很多 java 就麻烦的不行,要各个项目常驻内存,启动就得老半天。
|
![]() |
23
0xD800 61 天前
我用 java 写的一个 ddns ,根本不关注内存,crontab 一分钟跑一次
|
![]() |
24
0xD800 61 天前
我记得新版的 GC 是对大内存友好,对小内存好像不怎么友好,你试试 jdk8 用老的 GC 看看
|
25
Huelse 61 天前
话虽如此,但在大规模 IO 应用上 java 还是唯一选择
|
27
jackmod 61 天前
小工具应用我甚至已经决定放弃 Python 了,正在抓紧时间掌握 golang
|
28
dcsuibian 61 天前
不是 java 内存大了,是你内存小了。我个人 2c4g 的腾讯云轻量,根本没想过内存占用
|
![]() |
30
cocalrush 61 天前
你继续跑 1k 个链接任务,会发现仍然是这么大的内存
|
31
Donaldo 61 天前
说实话,你这个需求真没必要用 Java ,我估计在这个场景大部分内存都被 runtime 吃掉了,真正业务逻辑吃掉的内存少之又少。
|
![]() |
32
labdum 61 天前
|
![]() |
33
kuanat 61 天前 via Android ![]() 这一套跑起来要多少内存属于常识性问题,不是说那遇到过才知道的。另外企业级代码也要有企业级的运行环境做支撑啊,没有配套的环境谈什么企业级。
不如反过来你尝试回答这样一个问题,这个需求你还能用别的方式熟练的完成么?不能的话那你没得选,能的话说明决策有问题。 比如这个需求 mysql 换成 sqlite 不行么,裸写 sql 不行么,甚至说存自定义格式不行么?既然都是 http 请求加 json 解析,换成 Python 不行么,如果 python 不方便部署,换成 go 之类的不行么。 特别当你知道运行环境就是 1c1g 的时候,更应该考虑这些变通的手段啊。如果换成我的话这个需求我连 self host 都不会用,免费的 cf worker 比你的小主机可用性高太多了。也许你都没考虑过长期维护的事情。这种需求要的是省心,但你现在的选型和实施都没自动化的考量,配置一个简单的 cd/ci 之后这个差距会更大。 说这么多其实是想表达,不要把完成需求仅仅局限在写代码的层面上,当成项目来管理运营会更容易做出整体上更合理的决策。 |
34
Fule 61 天前 ![]() 纯粹说明一下个人对 @labdum 引用的那个文章的看法。
那个文章的作者大概不是对他列举的每一门语言都足够了解。我对其它语言了解不多,但是一如那个文章回帖里说的,C#的写法不太行,而且都 .NET 6.0 的测试环境了,创建如此大量 Task ,要不要考虑下 ValueTask 的可行性。我相信列举的其它语言的写法也有类似问题,所以那篇文章的参考价值是:一个某某语言的初级程序员在不充分了解语言特性和机制的情况下写出的未优化的代码的内存开销有多遭。 |
![]() |
35
selca 61 天前
graalvm 试试
|
![]() |
37
kandaakihito 61 天前
是这样的,而且 spring 那套脚手架即使是很熟练了起手也得搭半天
|
38
wysnxzm 61 天前 ![]() java 不设置内存大小默认使用物理机 1/4 内存与代码无关,按理说都用 jdk21 了不至于连这个都不知道啊
|
![]() |
39
xubeiyou 61 天前
。。。用 Java 了-- 肯定耗内存啊 这个东西 用地方越小 越不值当
|
40
Blanke 61 天前
都用 java 了还在乎啥内存
|
![]() |
41
yaott2020 61 天前 via Android
Java 缺陷就是内存大户,个人用肯定 Python/Go 更好
|
![]() |
42
cheng6563 61 天前
@wysnxzm 照你说的是不是一个物理机只能跑 4 个 Java 程序。
内存占用如此大就是 Hotspot JVM 的设计问题,Hotspot JVM 很不喜欢把已 GC 的内存还给操作系统,换 openj9 就没这问题了 |
43
zbatman 61 天前 ![]() Javaer 是这样的,JDK 维护人员只要全身心投入到底层,性能优化,添加新特性就可以,可是 Javaer 要考虑的事情就很多了。
|
45
kanepan19 61 天前
企业级代码 亮了,
话说,你可以指定堆内存,当然你这 spring 一套下来,200m 也差不多那样了。 |
46
afantwtz 60 天前
@diagnostics #20 然而这个情况我也会回“不知道”,多一事不如少一事
|
47
louisxxx 60 天前
你换 PHP 是不是就 10M 了
|
![]() |
48
VensonEEE 60 天前
这种事儿就是 Python 、node 、go 的事儿 ,java 的擅长点在生态利用、以及大型项目的编码组织上。
没有工具是万能的。 |
![]() |
49
tomatocici2333 60 天前
对于企业来说内存不值钱
|
50
Navee 60 天前
是这样的,可以换 openj9 运行环境,进一步减少内存占用,但还是解决不了“我就提供一个接口为什么占用几十 M 内存”的问题
|
![]() |
52
liuhuansir 60 天前
@Navee 因为 java 就是要占这么多,换语言就可以解决你的问题
|
54
LPJD 60 天前
才 250M?我们起步都是 2G 的
|
![]() |
55
xingjue 60 天前
要编译快 要省内存 直接上 go 吧 适合的语言做适合的事情
|
56
zzfly256 60 天前
在这类数据爬取的定时任务上,轻量点的脚本语言的性价比会更高;
另外不考虑一下利用 linux 的 crontab 吗,考虑到周期为 10 分钟一次的话,常驻进程应该大量时间都在空跑吧 |
![]() |
57
RandomJoke 60 天前
企业级大部分应用就是承载很多业务了,上手就是几 G 内存了,差距就拉小了,那种业务量很小的,你用个 lua + nginx 写写都行,根本没必要用 java 这种重生态的语言,java 的优势就在于生态非常成熟,就像 spring ,本身是让你依赖管理更加简单,你要是本身应用就很简单,有什么好管理的。
|
![]() |
58
mezhangkai 60 天前
用 quarkus 和 graal 21 拥抱云原生,压力内存,虽然相比 go 还是有些差距,但还是进步非常多。
|
59
w568w 60 天前
C/Zig/Rust/Go 占内存都小。说到底为什么要吊死在 Java 上?你也知道资源不足,还用企业级的 JVM 。要么 GraalVM 编译为原生,要么等 Kotlin Native 吧。
|
![]() |
60
libook 60 天前
java 默认是按照你物理内存大小按比例自动分配空间的,有配置内存分配的参数,比如 Xms 和 Xmx ,你看看是不是能解决你的问题。
|
62
Nitsuya 60 天前
我 N1 跑着各种代码, 差不多 400M.
X86 用 GraalVM 做 native 吧. |
![]() |
63
Torpedo 60 天前
淡定,之前在快手,听服务端的说公司 java 框架启动要 8g 以上的内存。
|
64
x2ve 60 天前
内存和带宽受限时,那种感觉是真难受。要是有能完美模拟浏览器行为且内存开销特别小的工具就好了
|
![]() |
65
caqiko 60 天前
|
66
wysnxzm 60 天前 ![]() @cheng6563 #42 https://stackoverflow.com/questions/60107793/why-default-java-max-heap-is-1-4th-of-physical-memory 这是 stackoverflow 上对于 jvm 默认内存大小的一个讨论,其中提到从 jdk5 开始就是如此
jvm 默认使用 1/4 内存对不对且不说,你要是有疑问完全可以给 jdk 开发者提 issue 我非常支持 但是都是用 jdk21 了还不知道一个从 jdk5 延续至今未变更的特性,这很不合常理吧? |
![]() |
67
joyhub2140 60 天前
springboot 已经是大规模企业级框架了,默认集成的组件也不少。
介意内存的话,Java 也有很多小而美的框架。 |
68
z836454898 60 天前
想要性能得用 go
|
69
blackmirror 60 天前
用 java 根本就不考虑小内存,小内存根本不会用 java
|
70
zhouhu 60 天前
要看内存实际使用情况吧,Java 申请了 256M ,不一定全部使用了,如果使用率较低,可以使用 xmx 限制一下最大内存。
|
72
Chinsung 60 天前
画个靶子自己打可还行,你这个诉求你既然对内存有要求就用 c 和 go ,用 java 就要考虑 GraalVM 。
你这个例子我可以用来吐槽任何语言。反正把那个语言的短板拿来直接套就完事了 |
73
cqjdcheng 60 天前
.NET,php 30M 就够了
|
![]() |
74
highFreqSurfer 60 天前
go 开发路过, 但建议用 nodejs (狗头
|
75
yazinnnn0 60 天前 ![]() |
![]() |
77
Features 60 天前
功能比你复杂很多的 php cli ( workerman )脚本,占用 5.3 MB
|
78
dode 60 天前
go 写,内存可以回收,java 内存占的是全生命周期内存需求最大的内存,不会释放回操作系统
|
![]() |
79
satoru 60 天前
大量 JVM 微服务,老板会很开心
|
![]() |
80
cmsyh29 60 天前
主要是 boot 自带了很多对象。其实你往上加一些正常业务,内存也不会涨的很明显
|
81
shanai 60 天前
用 Rust:)
|
![]() |
82
elevioux 60 天前
装 php 的时候加上 curl 和 mysql 扩展, 一个脚本搞定。然后让 crontab 定时运行 0 10 * * * php script.php 。
不运行,0 占用。 |
84
kenvix 60 天前 ![]() 优化内存占用从未是 Oracle JVM 的重点,它们只关注吞吐量
只有 ART 这种移动 JVM 才会稍微关注下这个事情 |
![]() |
87
loopq 60 天前 ![]() @diagnostics #20 瞎说,培训班出来的也知道命令行 javac 直接运行.java 文件,明明连培训班的都不如
|
![]() |
88
edisonwong 60 天前
shell + cron (doge
|
![]() |
89
Belmode 60 天前
噫嘘唏呜呼哀哉?
|
92
9c04C5dO01Sw5DNL 60 天前
用 rust 重写
|
93
yinmin 60 天前 via iPhone
如果程序不复杂,你可以试试把完整的 java 代码递交给 claude3.5sonnet ,让他改成 python 代码。
python 的启动速度和内存占用都比 java 好些。 甚至你可以让 claude 改写成 sh 脚本试试。 (我试过让 poe 里的 claude3.5-200k 把 cloudflare workers 的 js 完整代码改写成 python ,这货给出的代码居然能一次跑通,然后小细节沟通了几次,自己没写一行代码 100%完美运行) |
94
chainal7777 60 天前
试试 rust ,可能会变成 9M
|
95
bunny189 60 天前 via iPhone
“我的 hello world 怎么占用了 1 个 G”
|
![]() |
96
hillwall 60 天前
用 go 或者 node
|
![]() |
97
agdhole 60 天前
.net 8 aot 见
|
100
fox0001 60 天前 via Android
这个简单需求,可以用 go ,甚至 shell
|