Java使用的内存远远多于使用-Xmx分配的内存

时间:2013-03-07 21:32:32

标签: java memory memory-management stack

我正在编写一个项目(用Java编写),用于教授说我们不允许使用超过200米的课程 我使用-Xmx50m将堆栈内存限制为50m(只是为了绝对确定),但根据顶部,它仍然使用300m

我尝试运行Eclipse Memory Analyzer,它只报告26米

这可能都是堆栈上的内存吗?我很确定我从不会超过大约300个方法调用深度(是的,它是一个递归DFS搜索),所以这必须意味着每个堆栈帧都在使用几乎一兆字节似乎很难相信。

该程序是单线程的。有谁知道我可能减少内存使用的任何其他地方?另外,如何检查/限制堆栈使用的内存量?

更新:我现在使用以下JVM选项没有效果(根据顶部仍然约300米):-Xss104k -Xms40m -Xmx40m -XX:MaxPermSize=1k

另一个更新:实际上,如果我让它运行一点点(带有所有这些选项)大约一半的时间它会在4或5秒后突然下降到150米(另一半它不会下降)。这真的很奇怪的是我的程序没有随机(并且我说它是单线程的)因此没有理由它在不同的运行中表现不同

它可能与我正在使用的JVM有关吗?

java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.3) (6b27-1.12.3-0ubuntu1~10.04)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

根据java -h,默认的JVM是-server。我尝试添加-cacao和现在(所有其他选项)它只有59米。所以我想这解决了我的问题。谁能解释为什么这是必要的?另外,我应该知道哪些缺点?

还有一个更新:与服务器相比,可可真的很慢。这是一个糟糕的选择

5 个答案:

答案 0 :(得分:15)

Top命令反映了Java应用程序使用的内存总量。其中包括:

  • JVM本身的基本内存开销
  • 堆空间(以-Xmx为界)
  • 永久生成空间(-XX:MaxPermSize - 并非所有JVM中的标准)
  • 线程堆栈空间(每个堆栈的-Xss)可能会根据线程数显着增长
  • 本机分配使用的空间(使用ByteBufer类或JNI)

答案 1 :(得分:5)

使用-Xmx配置堆大小。要配置堆栈大小,请使用-Xss参数。这两个参数的总和应该大概是你想要的:

-Xmx150m -Xss50m

例如。

此外,还有-XX:MaxPermSize参数可供控制。 -client的此参数的默认值为32mb,-server为64mb。根据您的配置计算它。 PermGen空间是:

  

永久生成用于反映VM本身,例如类对象和方法对象。

所以基本上它存储了JVM的内部数据,比如类定义和内部字符串。

最后我必须说有一部分你无法控制,那就是本机java进程使用的内存。 Java是程序,就像其他任何程序一样,所以它也使用内存。如果您正在查看任务管理器中的内存使用情况,您将看到此内存以及程序内存消耗。

答案 2 :(得分:5)

Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]

这里max heap memory为-Xmx,min heap memory为-Xms,堆栈内存为-Xss 和-XX maxPermSize

以下示例说明了这种情况。我用以下启动参数启动了我的tomcat:

-Xmx168m -Xms168m -XX:PermSize=32m -XX:MaxPermSize=32m -Xss1m

答案 3 :(得分:1)

您是否尝试过使用JVisualVM?

http://docs.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html

我经常发现它可以帮助我追踪这些东西。它会向您显示每种内存的使用量,即使您可以深入了解并找出内容。

答案 4 :(得分:1)

重要的是要注意“使用的总内存”(Linux版本中的RSS)包括JDK堆(+其他JDK区域)以及分配的任何“本机内存”。

例如,这些人发现在GC之间分配太多jaxbcontexts(具有相关的本机内存)可能会导致它使用大量额外的RAM。另一个常见的显然是ZipInflater,如果你不调用它(或GZipStream等)

http://sleeplessinslc.blogspot.com/2014/08/jvm-native-memory-leak.html

他的最终解决方法/解决方案是“更频繁”GC(通过使用GC1垃圾收集器,或指定较小 [具有讽刺意味] -Xmx设置)或缓存JaxBContext对象(因为它们没有密切的方法,所以你无法控制泄漏。)

另请注意,有时您只需检查jstack即可找到记忆罪魁祸首:http://javaeesupportpatterns.blogspot.com/2011/09/jaxbcontext-performance-problem-case.html

有时也可能意外“错过”关闭例如GZipStream http://kohsuke.org/2011/11/03/quiz-time-memory-leak-in-java