[关闭]
@xtccc 2016-06-16T20:15:35.000000Z 字数 3522 阅读 2921

JVM内存模型

给我写信
GitHub

此处输入图片的描述

Java


参考:


背景知识


Method area & Heap

大体上看,JVM的内存空间可以划分为两类:



所有threads都可以访问的空间,可以分为两类:1) Method Area; 2) Heap ;

Class loader将加载一个class的字节码,并将其传递给JVM。Method area负责存储class相关的信息,包括以下数据区域:

不必对Method area中的空间进行GC。

QQ20151224-1@2x.png-348kB


Heap管理着所有的class实例(对象)及数组,JVM标准要求必须有GC机制对heap中的对象进行回收。

Generations

Heap可以被划分为两种generations:young generation(new generation)
old generation(tenured generation)

而Method Area则被划分为另一种generation:permenant generation

QQ20151224-0@2x.png-104.5kB



Young generation 也可以被称为 new generation,它可以被进一步分为3个区域:Eden, Survivor Space I,以及 Survivor Space II

当JVM创建一个对象时,它首先出现在 Eden,然后被移动至 Survivor I,然后再被移动至 Survivor II,最后被移动至 Old generation。

Minor GC 期间,JVM会将对象移动至young generation的各区域。
在GC时,如果old generation中没有足够的空间容纳对象,JVM会触发 Major GC 进程,这会对所有的Java App在性能上造成较大的负面影响。

我们可以告诉JVM应该将young generation和old generation的大小设置为多少字节,但是这只作为hint,真正的size仍然由JVM自己计算决定。参数 -XX:NewSize 可以设置young generation的初始大小,同时参数 -XX:NewRatio 可以设置 old generation 与 young generation 的size比例。例如,如果 -XX:NewRatio 设置为2,那么old generation的大小将是yound generation的大小的2倍。




Garbage Collecting


对象(objects)在heap中产生,且只要被引用,它们就是存活的(live)。在GC期间,gargabe collector会检查这些objects是否处于被引用的状态,如果不是的话,则会将其标记为“garbage”,并且随后清理这些objects。

Garbage Collector Roots

这是一类特殊的objects,它们不会被任何人引用,参考 GC roots如果一个object本身不是GC root,也没有被GC root直接或间接引用,则它就将被garbage collector收集并清理

有三类GC roos:



下面是一个例子

  1. public class MyFrame extends javax.swing.JFrame {
  2. // reachable via Classloader as soon as this class is loaded
  3. public static final ArrayList STATIC = new ArrayList();
  4. // as long as the JFrame is not dispose()'d,
  5. // it is reachable via a native window
  6. private final ArrayList jni = new ArrayList()
  7. // while this method is executing
  8. // the parameter is kept reachable,
  9. // even if it is not used
  10. private void myMethod(ArrayList parameter) {
  11. // while this method is running,
  12. // this list is reachable from the stack
  13. ArrayList local = new ArrayList();
  14. }
  15. }




OutOfMemoryError


异常发生的区域

OutOfMemoryError 异常可以发生在任意内存区域。

  1. 如果Garbage Collector无法为一个新的对象分配内存空间,就会抛出如下的异常 :
    Exception in thread "main": java.lang.OutOfMemoryError: Java heap space

  2. 如果试图在heap中分配一个超过了total heap size的array,则会抛出以下异常:
    Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit

  3. 如果method area没有足够的空间来创建一个新的class,则会抛出以下异常:
    Exception in thread "main": java.lang.OutOfMemoryError: PermGen space



OutOfMemoryError 也可以发生在哪些只能由某个thread访问的区域中:

  1. 如果JVM中有了太多的methods,没有足够的空间来创建新的method,则会抛出以下异常:
    Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

  2. 如果在native stack(JNI method call)中出现内存分配错误,则会抛出以下异常:
    Exception in thread "main": java.lang.OutOfMemoryError: (Native method)

  3. 如果OS没有足够的内存(例如其他的进程用完了全部的内存,或者swap space设置得太小),则会抛出以下异常:
    Exception in thread "main": java.lang.OutOfMemoryError: request bytes for . Out of swap space?


异常发生的原因

通常,引发 OutOfMemeoryError 的case有3种:


内存泄露

当某些objects拥有GC root reference,但是Java app的代码不会再使用到这些objects时,就称发生了memory leak,这些无用的objects我们不妨叫它们“loitering objects”,这些 loitering objects 会在JVM的整个生命周期中一直存在。如果Java app不断地产生loitering objects,那么内存空间最终将被耗尽,从而引发 OutOfMemoryError

例如,如果我们创建了 static collection,将其用作缓存。我们向该static collection中不断地加入objects(add/append/put),又从不删除这些objects(remove)。由于这些被加入的objects是被static collection引用的,因而它们是不能被GC清理的(因为:通过class loader,static collection拥有了GC root reference)。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注