Java非堆内存和堆栈内存有什么区别?如果它们不同,那么它们之间的区别是什么?

24

我正在使用Jconsole来监控Java应用程序。内存选项卡显示不同的堆和非堆内存,例如:

  1. 堆内存使用
  2. 非堆内存使用
  3. 内存池 "CMS Old Gen"
  4. 内存池 "Par Eden Space"
  5. 内存池 "Par Survivor Space"
  6. 内存池 "Code Cache"
  7. 内存池 "CMS Perm Gen"

这些术语之间有什么区别?另外,请提供一些关于如何通过监视这些参数来查找应用程序行为异常的信息。


2
可能是重复的问题,关于Java内存池如何划分的问题,请参见以下链接:https://dev59.com/q3M_5IYBdhLWcg3wt1g0 - icza
重复:https://dev59.com/q3M_5IYBdhLWcg3wt1g0?rq=1 - mikea
3个回答

18

在所有基于C语言(以及大多数其他语言)中,存储可以分为三个类别:

  1. 堆(Heap)
  2. 栈(Stack)
  3. 静态(Static)(有几个变体)

你熟悉堆。

栈也很熟悉,但你只是不知道它而已。当你有一个带有“本地”变量的方法时,“本地”变量会被分配到“调用帧”中。“调用帧”在调用该方法时分配,在从该方法返回时删除,因此最有效的实现方式是使用一个随调用增长并随返回缩小的“栈”。

静态是你没有明确分配的东西,而且从程序执行开始就存在。

栈所需的空间通常相当小,与上述类别中的“非堆内存”混合在一起。


7
你熟悉的"Heap"是什么? -- 是吗? - user64141
3
每当你使用 "new" 关键字时,就会使用堆内存。 - Hot Licks

15

非堆内存指的是JVM为除了堆以外的目的所分配的所有内存空间。这包括:

  • 调用栈(正如您所指出的);
  • 由本地代码分配的内存(例如,用于离堆缓存);
  • 在HotSpot 8中,元空间(永久代替换);
  • JIT编译器使用的内存(编译后的本机代码)。

在您的列表中,“CMS Old Gen”,“Par Eden Space”,“Par Survivor Space”和“CMS Perm Gen”都指向堆的各个部分。


2
请跟随以下链接:http://www.yourkit.com/docs/kb/sizes.jsphttp://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.50%2Fdiag%2Fproblem_determination%2Faix_mem_heaps.html 非堆 此外,JVM还有除堆之外的内存,称为非堆内存。它在JVM启动时创建,并存储每个类的结构,例如运行时常量池、字段和方法数据以及方法和构造函数的代码,以及interned字符串。
不幸的是,JVM提供的关于非堆内存的唯一信息是其总大小。没有关于非堆内存内容的详细信息可用。
非堆内存大小异常增长可能表明潜在问题,在这种情况下,您可以检查以下内容:
如果存在类加载问题,例如泄漏的加载器。在这种情况下,可以使用Class loaders view解决问题。 如果大量使用字符串进行interned。为检测此类问题,可以使用Object allocation recording。

最好不要链接到外部网站,因为页面经常被移动或删除,链接会变得失效。 - PeterToTheThird

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