Java hello world 确实就要占用 30M

64 天前
 javak

最近看了几个帖子都是说 java 内存的, 自己也写 java , 还从来没关注过一个 hello world, 今天一时兴起测试了下,确实需要占用 30 。

测试方法和代码如下:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("hello memory 02");
        Thread.sleep(60 * 60 * 1000);
    }
}

方式 1: 直接运行 java Main.java 。70M 内存

方式 2: 先编译,再运行: javac Main.java, 然后 java Main. 30M 内存

方式 3 编译成 jar 包在运行,java -jar main.jar 30M 内存。 编译的 maven 配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>untitled</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

以上的 java 运行环境:

openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)

如果觉得上面哪里测试有问题的,欢迎来拍。

一句话总结:Java 内存没救了,在意内存别用 Java 。

11445 次点击
所在节点    Java
113 条回复
mikewang
63 天前
不知道你有没有用过那种老的翻盖手机,那时的手机的 RAM 才多大点,但是从贪吃蛇到飞机大战,还有 3G 联网的打牌游戏,都是 Java 写的。
zcybupt2016
63 天前
反正内存不用我掏钱
sagaxu
63 天前
@shuimugan 节省资源换 Go 我是理解的,但是换.net 这个无论是内存还是 CPU 都跟 Java 半斤八两的,就比较搞笑了。
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/java.html

Java 8 到 Java 21 不敢,拿 C#重写却很勇敢,这思路也是绝了。大部分 Java 8 写的后端服务,升级到 Java 21 基本上不用改代码能过所有测试用例,兼容性是极佳的。再怎么说也比换语言重写更稳。

Java 并发一堆坑? Netty/RxJava/akka/Vertx 没一个能用?稍微有点技术深度的人不能立刻上手?脑子转不过弯必须用同步方式写代码的,就是用 Kotlin 协程重构那也是在 Java 生态内玩,比直接换语言换生态容易的多。

业务到顶甚至下行的 Java 生态为主公司多了去了,有几个折腾换了.net ?可见换语言未必是符合公司利益的选择。
不得不承认,C#的语法设计,语言表达能力,那是比 Java 强不少的,换完 C#可以砍掉更多的人。
diagnostics
63 天前
@javak 同样的代码,你测试一下 nodejs ? Java 应该比 nodejs 还要少点的
humingk
63 天前
内存没有那么值钱,我正在上的 20 分片单实例 https://ibb.co/KXxQcGP 而这样的实例还有 10 个
anzu
63 天前
java 跑在虚拟机上啊,为了一次编译可多平台执行。
hez2010
63 天前
@sagaxu 那些 benchmark 都是在用空间换时间,当然内存占用大,对于内存占用水平而言没有参考意义,难道 c++的代码里直接在内存里打个表来优化性能,而别的语言的实现里没有这么做,导致 c++占用大就能说明 c++内存占用大了?

另外,.net 的内存占用一般要比 java 小一个数量级,比如 op 的测试代码原样翻译成 c# 后测试,

这是 .net:



这是 java:

sagaxu
63 天前
@hez2010 hello world 只能体现 VM 启动开销,并不能体现数据量增长时的内存增长情况。

“那些 benchmark 都是在用空间换时间,当然内存占用大,对于内存占用水平而言没有参考意义”

这个论断有两个问题,

1. 用空间换时间,难道只有 Java 版代码没这么干?

2. 高内存占用算法下,不是更能体现内存随数据量增长情况?

单 case benchmark 不能说明问题,多组不同类型 task ,多种实现,纵向横向对比下来,就足够看出一些端倪了。
shuimugan
63 天前
@sagaxu java 的并发方案,真要用起来,除了 kotlin 和新的虚拟线程,其它方案就是屎山制造机,用在项目里简直是害群的马。
换 Go 我也是能理解的,不过人家切到.net 之后,还完成了 DDD 的切换,这点应该是他们比较关注的收益,而且他们完成切换的时间节点可能还没等到 java21 的发布,这样看能选择的方案就很少了,切到.net 也可以理解。

如果你认可“大部分项目的瓶颈都不在语言本身而是数据库”类似的观念,那么应该关注的 http server 、序列化这种代码出现占比高的 case 的表现,在 https://programming-language-benchmarks.vercel.app/problem/http-server 这个测试里 kotlin 表现不算好,甚至还有超时的没跑完测试的情景,这就让人望而却步了。

而在这个 java vs csharp 的对比里 https://programming-language-benchmarks.vercel.app/java-vs-csharp 更亮眼的是开启 aot 后的表现,资源占用非常优秀,尝鲜的人多了之后,出现在技术选型里的几率就会慢慢变大。

硬切换对带头人的魄力和领导力有很强的要求,在国内很罕见,要做到精益求精也要讲生活和工作平衡。但对于开新坑的项目,切换技术栈就不难了,久而久之可能就会以绞杀者模式的形态完成了切换。
ragnaroks
63 天前
个人经验,技术栈较老(传统)的 java 项目都不在意资源消耗,比较新(特别是跑在容器里面的)的要么不会考虑 java 要么是 go 。业务复杂之后资源占用也不是需要优先考虑的事情,spring 吃个 10G 、aspnet 吃个 3G 、gin 吃个 1G ,对于跑这个业务的人来说没有区别。
sagaxu
63 天前
@shuimugan

那个团队原先 JPA 都不用,从 mybatis plus 切到 JPA 同样可以 DDD 化,而 JPA 在 Java 5 时代就有了。

用 Netty 和 Vertx 的回调风格项目我都写过几年,写业务逻辑是麻烦了点,写写基础组件挺顺手的。

Kotlin Ktor 性能并不好,也不成熟,支持的协议不多,并不是推荐姿势。Kotlin 后端开发,要么用 SpringBoot WebFlux ,要么干脆点用 Vertx/quarkus ,都能跟 coroutine 无缝衔接。按照那个 httpserver benchmark ,rust 比 go 和 js 都要慢的多。

.net AOT 目前还不成熟,官网上还写着 The Native AOT feature is currently in preview 。使用上也存在诸多限制和不便,跟 Java 那个 AOT 一样麻烦,虽然经过预编译耗时要短的多,也都算不上 production ready 。

老项目硬切是权斗,是政治问题,非技术问题。新项目要考虑技术负责人的积累,是从 0 开始踩坑,还是用最有把握的东西,我想大部分人会求稳。市场上的存量开发人员,无论资深资浅,国内用 C#的比例较低,等它先超过 nodejs 再说吧。

现阶段 Go 已经是云原生时代扛把子了,这个领域眼下还看不到强大的对手。
iseki
63 天前
JVM 的初始内存消耗就是很大,它提供了 go runtime 缺失的太多功能。至于跑起来的话,虽然 JVM footprint 偏大,但实际内存消耗还是要看程序怎么写。
needpp
63 天前
@wjx0912 这种已读乱回的风格着实让人喜欢
itakeman
63 天前
@diagnostics 我没看到谁提 golang ,倒是看到你提,用 go 的人看都不会看一眼 java ,java 什么东西?用 go 的只会看看 c 、rust 、Python 、js ,Java 什么东西?放垃圾桶去比较合适。用 java 的整天黑 go ,这不应证了 java 的衰落。op 主说 java ,你又来提 go 了。当然的我也希望 java 红红火火,免得一帮用 java 的人转 go ,写的代码 j 里 j 去
itakeman
63 天前
@haython qt 确实,Windows 没救了,拿 win 做家用路由器的厂商,估计来一个倒闭一个。用 linux 做家用路由器的厂商,各个风生水起
itakeman
63 天前
@CSM rust 学起来难么?
daysv
63 天前
@diagnostics 想啥呢, 我试了下 node 是 7.1mb , 所以我说 java 居然比 v8 初始化还占资源。
diagnostics
63 天前
@itakeman #94 v2 很多帖子,咱也不是张嘴就来,你统计一下就知道谁天天碰瓷了
diagnostics
63 天前
咱也不知道你用的是什么高阶 Node ~

83 67 root S 263m 1% 2 0% node main.js
67 0 root S 1704 0% 12 0% /bin/sh
103 0 root S 1672 0% 11 0% /bin/sh
109 103 root R 1596 0% 12 0% top
/app/website # node -v
v18.18.2
/app/website # cat /proc/version
Linux version 5.4.0-122-generic (buildd@lcy02-amd64-095) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022
/app/website # cat /etc/issue
Welcome to Alpine Linux 3.18
Kernel \r on an \m (\l)

------------------------------------------------------------

27095 root 20 0 12152 3332 2736 S 0.0 0.0 0:00.02 bash
27129 root 20 0 2529768 23272 15708 S 0.0 0.1 0:00.16 java
27169 root 20 0 48432 3712 3132 R 0.0 0.0 0:00.00 top

[root@xxxx /]# java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (Zulu 8.42.0.23-linux64)-Microsoft-Azure-restricted (build 1.8.0_232-b18)
OpenJDK 64-Bit Server VM (Zulu 8.42.0.23-linux64)-Microsoft-Azure-restricted (build 25.232-b18, mixed mode)
[root@account-tn-9bcc7dc9-6tm2h /]# cat /proc/version
Linux version 5.4.0-122-generic (buildd@lcy02-amd64-095) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022
whyso
63 天前
@itakeman 用 go 的人看都不会看一眼 java ,java 什么东西?用 go 的只会看看 c 、rust 、Python 、js ,Java 什么东西?
暴躁老哥,我喜欢,哈哈。一个 hello world 就得写一堆

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

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

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

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

© 2021 V2EX