【问题标题】:How to minimize the memory used by my application?如何最小化我的应用程序使用的内存?
【发布时间】:2012-04-29 18:24:52
【问题描述】:

我正在编写一个具有约 30 个类的 Java/Swing 应用程序,我的问题是当我运行我的程序时,它会加载超过 150 M 的内存,这正常吗?由于应用程序有 4 个线程,解析一些 XML 文件,加载一些图标文件,并绘制一些 Jfreechat 图表。 如果不是,我该怎么做才能最大程度地减少应用程序使用的内存量,是否会影响某些变量为空帮助?是加载一次 XML 文件以在所有应用程序生命周期帮助中使用它们,还是每次需要它们时都必须加载它们?还有其他一些对我有帮助的提示吗?

PS:我使用 8G 内存的计算机进行开发,以防影响我的程序使用的内存。

编辑: 看来该程序并未占用全部 150MB,因为我通过在我的应用程序中运行此代码从 linux 上的 top 命令获取此值,vilmantas 建议我:

   long free = Runtime.getRuntime().freeMemory();
   long total = Runtime.getRuntime().totalMemory();
   long max = Runtime.getRuntime().maxMemory();
   long used = total - free;

我发现他占用的内存远少于那个 (~40MB),所以我决定使用 "-Xmx40M" 参数运行它,并且我在 Top 命令中减少了 40% 以上的内存使用量。 自从JVM (据我所知) 有自己的进程 以及如何使这个操作自动**?** 因为在选择时,谁占用了其余内存的问题一个不合适的值,你可以通过运行 "-Xmx30M" 参数来获得内存异常:

   Exception in thread "Thread-2" java.lang.OutOfMemoryError: Java heap space

【问题讨论】:

  • 使用分析器(例如最近的 JDK 附带的 visualvm)来找出你的内存首先要去哪里。
  • 你在类路径中添加了多少个外部库?
  • 我正在使用 4 个外部库 jfreechat、snmp4j、commons-net-3.1 和 jdom-1.1.3
  • 你是通过 SAX 还是 DOM 解析的?
  • 这个库不能使用这么多内存。你能写你的jvm版本吗,你用的是32-x还是64-x模式?

标签: java optimization memory-management


【解决方案1】:

是的。这是 Java,通常您的 VM/GC 会为您完成这项工作。在出现问题时担心内存使用情况。
如果您愿意,有几种工具可以帮助您分析正在发生的事情。 How to monitor Java memory usage?

【讨论】:

  • +1 您可以使用 VisualVM 或商业分析器来查看什么正在使用多少内存。这是发现您可能会进行哪些更改以减少使用量的最佳方式。
【解决方案2】:

如果引用变量的生命周期大于引用的实例,将变量设置为null 有助于防止内存泄漏。因此,应该在整个应用程序生命周期中保持不变的变量最好不要保持对短期使用的临时对象的引用。

如果您擅长仅加载一次 XML 信息,则仅加载一次 XML 会有所帮助。意思是,如果不是通过您的应用程序更改了 XML,并且您需要获取更新 - 您将不得不重新加载 XML(如果不再需要已弃用的 XML 信息 - 摆脱它)。

【讨论】:

  • 将变量设置为 null 是否会调用 GC 来完成他的工作?或者只是清理引用并等待块结束?
  • +1 它很少需要,但这可能意味着您不会保留不需要的对象。它不会使 GC 更有可能运行。
  • 我的 Xml 文件是静态的,所以不需要重新加载,但问题是我不确定我是否会在依赖用户输入和操作的所有应用程序生命周期中使用它们,最大的问题是它们的大小超过 3M(2 个文件)
  • 8G 机器中的 3M 并不多。 3MB 相当于大约 2 美分的内存,并且可以重复使用。
  • 虽然设置为 null 是一个很好的建议,但请不要盲目地遵循它,只有在有理由的情况下才将变量设置为 null。阅读本文,不要试图智取你的 GC:stackoverflow.com/questions/627784/…
【解决方案3】:

您可以使用诸如http://www.eclipse.org/mat/ 之类的Java 内存堆分析器来识别应用程序中占用大部分内存的部分。然后,您可以优化您的数据结构,或者通过将所有对数据的引用设置为 null 来决定释放部分数据。

对不再需要的数据的意外引用也称为“内存泄漏”。设置那些对 null 的引用将导致垃圾收集器将其从 java 内存堆中删除。

沿着这条线,您可能会发现WeakReferences 很有帮助。

【讨论】:

    【解决方案4】:

    你在哪里观察到这 150M?这是你的 JVM 进程占用了多少(例如,在 linux/unix 上的 top 命令中可见)还是你的应用程序真正使用(和必要)的内存?

    在您的应用程序运行时尝试编写以下 4 个值:

        long free = Runtime.getRuntime().freeMemory();
        long total = Runtime.getRuntime().totalMemory();
        long max = Runtime.getRuntime().maxMemory();
        long used = total - free;
    

    如果“used”的值远低于 150M,您可以添加 java start 参数,例如“-Xmx30M”将应用程序的堆大小限制为 30MB。请注意,在这种情况下,JVM 进程仍然会占用 30MB 以上的空间。

    JVM 的内存使用有点棘手。

    【讨论】:

    • 是的,我从顶部命令观察这个值,我运行你的代码,我得到的值从 40MB 到 80MB 或更多,我猜是为了让 JVM 使用其余的值。我尝试使用参数 -Xmx30M 运行应用程序,它给了我一个内存异常“线程“Thread-2”java.lang.OutOfMemoryError:Java 堆空间中的异常”,并且使用参数 -Xmx40M 它可以正常工作并且进程现在占用〜80MB。这里的问题是我总是检查用于给出适当参数的内存,现在有自动解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多