即使对于小程序,Java 内存使用率也很高

2022-09-01 07:05:53

我有几个用java编写的简单应用程序,其中一个编写为充当小部件。令我惊讶的是,即使是小型应用程序也使用了多少RAM。

我写了以下内容,看看它是我的程序中的错误,还是一般的Java问题:

public class ram {
    public static void main(String[] args){
    while(true)System.out.print("Hello World");//while loop to give me time to check RAM usage
    }
}

然后编译并运行它,它给了我以下RAM使用情况:java ram

The process java (with pid 4489) is using approximately 43.3 MB of memory.
34460 KB    [heap]
7088 KB /usr/lib/jvm/java-7-openjdk/jre/lib/amd64/server/libjvm.so
1712 KB /usr/lib/jvm/java-7-openjdk/jre/lib/rt.jar
136 KB  [stack:4495]
120 KB  /usr/lib/jvm/java-7-openjdk/jre/lib/amd64/libjava.so

是不是太高了?特别是34MB的堆。我的系统是 ArchLinux x86_64 和 openjdk-7。

有没有办法最大限度地减少JVM使用的RAM量?

编辑:我尝试使用-Xmx标志,这就是我得到的(1281k是最小的,它可以让我开始):

java -Xmx1281k ram
The process java (with pid 4987) is using approximately 27.6 MB of memory.
18388 KB    [heap]

相比之下,Python2使用4.4MB,Mono使用4.3MB。


答案 1

我经常看到类似的问题,我还没有看到满意的答案。

我最常看到的答案是愤怒的“你为什么在乎?”答案。有些人花了很多心思和精力来解决这个问题,无论谁问它,看起来都很愚蠢。

有些人会用很长的谩骂来回答这个问题,关于Java分配的不同类型的内存,为什么这样做,以及你应该研究哪些命令行参数。(很少有人会非常具体)

事实是,对于小型实用程序,Java在大多数操作系统上都是内存占用。效用越小,它实际上就越明显。Java开发人员长期以来一直习惯于处理或忽略这一事实。

看似异常的内存使用的原因很多。每个线程为其堆栈获取一定量的内存。有几个线程可以开始,无论程序对于垃圾清理,RMI等事情有多简单。在Windows / 64位上,每个线程1MB。默认情况下会加载一堆类和所有类。我敢肯定,还有很多其他的事情正在幕后发生。

Java已经做出了其他语言没有的权衡选择。加载时间比大多数其他语言慢。初始内存要求更高。最常用的字符串消耗的内存比大多数人意识到的要多得多。还有无数其他的。在许多情况下,好处确实得到了回报。像Hello World这样的东西比其他任何东西都更能炫耀这些选择的成本。像简单的多线程和接近原生的性能这样的好处对Hello World没有任何好处。

不幸的是,您无法做很多事情来真正最小化简单应用程序使用的内存。有前面提到的命令行开关和试错可能会将您报告的使用量缩小到~10-15mb的水平,我敢肯定,但是这些选择和您花在弄清楚它们上的时间不适用于各种未来的应用程序。对于下一个应用程序,您必须再次经历相同的过程。放入一个GUI界面和一些日志记录以及另一个或两个通用库,您的基本编号将非常快速地拍摄到60mb。

你没有做错任何事。这只是Java中的工作方式。你会习惯的。你偶尔会因此选择另一种语言,这也没关系。


答案 2

这有几个原因:

  1. Java运行时本身就是一个相当复杂的程序。它需要获取Java程序的字节码(javac的输出),将其转换为运行它的系统的机器代码,有一个优化器,有用于调试的接口等。
  2. 虽然你的程序相当小,但Java仍然会从其标准库中加载许多类。您可以通过使用'java -verbose:class ram'启动它来观察这一点。
  3. Java提前为您的程序分配了大量的内存 - 它无法知道它实际上需要多少内存。除其他外,这由-Xmx选项控制。有几种类型的此类内存。要了解有关它们的更多信息,您可以使用JConsole工具,该工具包含在JDK的bin文件夹中。您可以在 java.sun.com 阅读更多相关信息。Java使用的内存区域的摘要也在这个堆栈溢出问题中给出