Java -Xmx,系统中的最大内存

24

我的Java应用程序通过运行进程"java -jar j.jar"来运行另一个Java应用程序。根据它所使用的数据集,J.jar已知会使用大量内存,并经常因OutOfMemoryError堆而导致崩溃。因此,我想在其上使用-Xmx,以便可以分配尽可能多的内存(或接近最大值)。我考虑获取系统上的总内存,然后在-Xmx中指定该内存的80-90%。

有什么解决方案可以解决我的问题吗?我的解决方案听起来如何?

编辑:我无法减少内存消耗,因为正在使用Java内置的pack200压缩进行压缩,我正在使用它来打包一些JAR文件。


4
您实际上在询问如何使用Java来确定系统内存的数量? - Michael Myers
是的,那将是一个可能的解决方案,如果您知道其他方法,我们会非常感激。 - Amandeep Grewal
你正在运行64位的JVM吗?因为如果你运行32位的话,那么如果你的可用内存显示为7G,那么你在处理80%的数据时会遇到问题。 - Ryan Fernandes
有没有C++的等价物? - Open the way
可用于JVM的内存应基于数据集的大小,而不是本地主机上完全无关的可用内存。为了实现与本地内存无关的可扩展解决方案,请使用分布式缓存。 - michael
7个回答

13
-XmX的限制在32位Windows上为-Xmx1500m。 共享库妨碍了更大的堆。 您需要约2GB的RAM才能完成此操作。 在非Windows操作系统上,可以扩展更大的堆,而64位JVM可以处理更多的堆。 Windows XP不允许您拥有超过3GB的RAM(无论您是否有4GB物理内存,自从XP SP3以来都是如此),但Vista可能有所不同,因人而异。 我曾经在64位Linux上使用64位JVM尝试过-Xmx4000M,效果良好。考虑到我有6GB的物理内存,这并不是一个很大的请求。 您提出的80%的想法很有趣,但是我的测试系统运行的百分比比80%还要高,没有不良影响(只要您不尝试做其他事情)。 另一个评论者是正确的,将JVM的内存映像换出是不快的。后期的JVM在执行这项任务时更有效率(但它们也有更好的垃圾回收器)。 如果您无法减少内存消耗 - 我知道这有多难 - 那么请拥有大量的物理内存并分配其中大部分。

5

根据你的操作系统,可能会通过以下方法获取可用内存大小:

java.lang.management.OperatingSystemMXBean mxbean = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean;
long freeMemory = sunmxbean.getFreePhysicalMemorySize();
long availableMemory = sunmxbean.getTotalPhysicalMemorySize();

从这里开始,您可以计算出80-90%的内容,并使用您想要的最大内存大小启动您的jar文件。

我不知道这是否适用于所有操作系统(例如Windows),但在我测试过OSX和Linux时有效。


2
谢谢!我在Windows和Linux上尝试了那个命令,它完美地运行了。 - Amandeep Grewal
2
看起来这只能在Sun JVM上运行,我需要部署到IBM JVM,所以不能在每个人都使用Sun的情况下运行。 - David Waters

5

0

嗯,我可以告诉你的一件事是不要让你的应用程序接近填满内存。Java 应用程序根本不会优雅地进行交换。我认为这是因为垃圾收集,Java 不断地从交换中提取其内存。

我遇到了一个僵局,在那里我认为系统正在请求 Java 的内存,这将导致 GC 并从交换文件中拉出东西--此时系统将一直旋转,直到我重置它。

这是在有很多 RAM 和很多交换空间(当时)以及旧版本的 Java VM 下发生的,所以你的结果可能会有所不同。

另外,取决于你如何启动另一个应用程序,你可能需要为你的应用程序指定 -Xms,而不是其他应用程序。如果你给它一个完整的命令,请给它 -Xms,但如果你只是调用 jar 中的主类,则你的应用程序需要 -Xms。(哦,你已经指定了,是的,你需要将其传递到你正在调用的 "Java" 命令中。)


0

你使用操作系统来执行jar包中的程序有什么原因吗?如果你不需要它在应用程序的独立进程中执行,你可以直接从代码中调用主方法,并使用任何你想要的-Xmx启动你的应用程序。


启动其他应用程序或启动我的应用程序都存在相同的问题。如果我使用其主方法运行其他应用程序,我仍然需要我的应用程序能够使用大量内存。 - Amandeep Grewal

0

0

如果你还没有这样做,你需要通过内存分析器运行你的程序。你可能会发现某些数据结构即使不再使用也没有被处理掉。

JProfiler非常棒,但是你可以使用在Java 5中引入的HPROF获得相同的信息:http://java.sun.com/developer/technicalArticles/Programming/HPROF.html

请记住,不同的平台基于架构(32位与64位)、操作系统甚至JVM有不同的最大堆大小。

如果你有很多可能被重复使用的值(例如从XML文件中读取的字符串),通过对象池化可以大大减少内存需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接