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

Posted

技术标签:

【中文标题】即使对于小型程序,Java 内存使用率也很高【英文标题】:High Java memory usage even for small programs 【发布时间】:2012-11-21 10:44:18 【问题描述】:

我有几个用 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
    

然后用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。

【问题讨论】:

How to set the maximum memory usage for JVM? 的可能重复项 谁在乎?虚拟内存基本上是免费的。现代系统可以以接近零的成本大量生产。这就像试图呼吸更少的空气。 (注意这里不是测量物理内存、RAM,而只是测量虚拟内存、地址空间。) 43MB 并不奇怪,因为 JVM 为将来可能的负载预留了足够的内存。但如果你将 max mem 设置为几 MB 应该没问题 JVM 确实使用[相对]大量内存。虽然 David 确实指出它是“虚拟的”,但我认为与本机应用程序相比,这可能会掩盖典型 Java 环境所涉及的开销(尤其是当应用程序“什么都不做”但启动时) - 那么这与物理使用?我不知道.. @TomG 有时这与 RAM 的成本无关,因为某些设备只能拥有这么多内存(Raspberry Pi:265/512MB RAM,我的上网本:2GB) 【参考方案1】:

这有几个原因:

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

【讨论】:

【参考方案2】:

我经常看到与此类似的问题,但我还没有看到令人满意的答案。

我最常看到的答案是愤怒的“你为什么在乎?”答案。有些人花了很多心思和精力来提出这个问题,而提出这个问题的人似乎很愚蠢。

有些人会用长篇大论来回答这个问题,关于 Java 分配的不同类型的内存、为什么这样做以及您应该查看哪些命令行参数。 (很少有人说得很具体)

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

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

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

不幸的是,您无法真正最大限度地减少简单应用程序使用的内存。有前面提到的命令行开关,我敢肯定,反复试验可以将您报告的使用量缩小到 ~10-15mb 水平,但是您花在弄清楚它们上的那些选择和时间并不适用于各种各样的未来应用。对于下一个应用程序,您必须再次执行相同的过程。加入一个 GUI 界面和一些日志记录以及另一个或两个通用库,您的基数将很快达到 60mb。

你没有做错任何事。这就是 Java 的工作方式。你会习惯的。有时你会因为它而选择另一种语言,这也没关系。

【讨论】:

感谢您花时间提供一个平衡的答案,没有通常的愤怒(在任何一个方向)+1 这是一个绝妙的答案。似乎解决了这个难题。 为什么 C# 使用更少的内存?例如,我通常看到 intellij、Eclipse 或 netbeans 使用 1gb 的 ram,但 Visual Studio 只使用 300mb。我还看到了其他 c# 程序,例如paint。 Net,根据任务管理器的说法,它们也使用很少的内存。 @pavel 可能仅在 windows 上运行的 c# 具有更好的优化,例如利用系统资源等,另一方面,JVM 需要在其他平台上工作必须实现自己的魔法。我可能错了。 谢谢!我得到的最佳答案。其他所有答案都像是“因为新计算机有足够的 RAM,所以没关系”。我是一名 C++ 程序员,这就是为什么这对我来说是一个有趣的话题。真的,非常感谢。

以上是关于即使对于小型程序,Java 内存使用率也很高的主要内容,如果未能解决你的问题,请参考以下文章

JVM内存模型

Java 内存消耗很高并且还在增长

Java内存CPU占用率过高

G1垃圾回收器

对于小型/大型 numpy 数组,释放的处理方式是不是不同?

IIS 工作进程对同一服务器上的相同站点的内存使用率很高