9

我曾参与过一些以实现更好的性能和减少内存消耗为主要目标的项目。但是相信我,在 Java 中控制内存消耗已经很困难了。

这个wiki 页面在“ Java 程序速度” 上说Java 在某些情况下在低级和数字基准测试上等于 C++。

这些统计数据并没有真正显示时间计算性能基准的主要差异。但是,Java 中的内存使用量比 C++ 高得多,因为在 Java(32 位;在 64 位 java 中是两倍)中,每个对象有 8 字节开销,每个数组有 12 字节开销,如以上维基链接。

现在的问题是人们采取了哪些措施来最小化 Java 中的内存利用率?

请注意,我更关心内存而不是性能,因为我想不出比“编写更好的程序”和“在 JDK 中正确调整内存”更好的方法

4

4 回答 4

5

根据您的工作内容,您可以从不同的编程实践中受益,例如:

  • 在实际使用它们之前限制您初始化的变量数量。
    • 只是一个一般的良好编码技巧。已初始化且暂时不需要的变量正在占用尚不需要的内存,这可能会浪费资源。
  • 在适用的情况下通过静态对象进行对象缓存。
    • 我之前在反射繁重的应用程序中使用过它,我需要在循环中获取对象上的成员列表,它可以根据可能需要的情况显着提高性能。
  • 适用的对象池
  • 如果您正在编写多线程应用程序,您可以利用线程池来通过限制创建和启动新线程的工作量来获得性能。
于 2012-09-24T04:26:31.337 回答
3

在 java 中管理内存可能有两个动机。

1. 避免频繁创建/删除对象。

这反过来又避免了 GC 频繁唤醒,因为这会导致一个或多个正在执行的线程挂起。

避免临时/永久内存漏洞

2.降低VM的整体内存消耗

如果您的 VM 将在具有严格内存限制的环境中运行,则需要这样做。

理想情况下,从内存的角度来看,一个编写良好的 java 程序应该尝试实现上述两个目标。现在要实现 1,您应该执行以下操作。

  • 首选静态内存分配,即每个 VM 分配一次,而不是动态内存分配。

  • 避免在函数中创建临时对象,为此大多数对象可以实现一个 reset() 方法,该方法可以允许对象重用

  • 了解您正在使用哪个 API,例如。如果您使用 String,您
    最终将创建与修改一样多的实例。这同样适用于自动装箱类型。

以上几点也有助于管理或控制第 2 点

要检查 VM 内存大小,您需要执行上述几点并执行以下操作

在启动 VM 时使用 Xmx 和 Xms 标志,并故意将它们的值设置为低于可能需要的值,并注意 OutOfMemoryError 。

如果 OutOfMemoryError 发生,这意味着您超出了最大 VM 大小。确定原因并开始调整您的对象创建。

希望能帮助到你 ...

于 2012-09-24T04:54:50.320 回答
2

人们采取了哪些措施来最大限度地减少 Java 中的内存使用?

他们着眼于小型基准测试,而不是阵列大小的微观测试。

您可以尝试将 Java 的引用(即使在 64 位 JVM 上也使用 4 字节)与 C++ 共享指针(可以在 64 位进程上使用 48 字节)进行比较,并得出一些不太可能在真正的节目。

我更关心内存而不是性能,因为我想不出比“编写更好的程序”和“在 JDK 中正确调整内存”更好的方法

通常你需要做的就是使用内存分析器。这将帮助您最大限度地减少 Java 中的内存消耗。

我发现这种对保存每个字节的痴迷在大多数情况下是不合时宜的。在 PC 中,一个字节的内存成本约为 5e-7 美分。或大约 2e-6 秒的时间。这些可以加起来,但如果您只节省 100 KB,则可能不值得更改任何代码来执行此操作,如果您要节省 1 GB,则可能值得花几个小时。即使您确实节省了 1 GB,内存也可以重复使用,但您的时间却不是。

“如果内存是主要限制因素,那么你需要 java 有什么理由吗?”

我同意这一点,如果你有一个只有几 MB 的设备,例如比安卓手机还小,C 将是你的最佳选择。如果您的设备至少具有智能手机容量,那么 Java 可能适合您的需求。

于 2012-09-24T06:28:06.750 回答
2

除了减少您创建的对象数量并尝试使您的对象短暂存在之外,您对内存无能为力。但是,Java 仍将使用它允许的所有内存以获得最佳性能。

于 2012-09-24T04:23:18.913 回答