jvm内存模型

jvm内存模型可以分为 堆、方法区、虚拟机栈、本地方法栈、程序计数器五个区域。见下图。

jvm内存模型

1.方法区

方法区是各个线程共享的内存区域,用于存储类的信息、常量静态变量

HotSpot VM把方法区也称为永久代,Permanent Space。永久代对垃圾回收没有显著影响。

1.1 vm参数

-XX:PermSize //永久代最小空间

-XX:MaxPermSize //永久代最大空间

示例: -XX:PermSize=100m -XX:MaxPermSize

1.2相关报错

java.lang.OutOfMemoryError:Perm space

永久代内存溢出,调大内存即可。

2.堆

堆通常是jvm内存中最大的一块,用于盛放对象。

堆又可以分为新生代与老年代,见图2-1.

jvm内存模型
图2-1 jvm堆与方法区的内存模型


permanent space为永久代空间;heap space为堆空间,它又分为新生代空间与老年代空间。

2.1新生代空间

它又可以分为2部分——Eden space与Survivor Spaces,后者包括s0与s1。

2.1.1 Eden space

Eden ['i:dən] n. 伊甸园(《圣经》中亚当和夏娃最初居住的地方)

新创建的对象将放入Eden Space。

2.1.2 survivor space

又可以分为 s0  (survivor 0) 与 s1(survivor 1)。

Eden区满时,触发一次minor GC。还存活的对象将被复制到s0,同时清空Eden区域。

Eden区再次满时,触发一次minor GCEden+s0(不管s0有没有满)还存活的对象将被复制到s1,同时清空Eden+s0区域。

Eden区再次满时,触发一次minor GCEden+s1(不管s1有没有满)还存活的对象将被复制到s0,同时清空Eden+s1区域。

如此往复。。。

注意survivor from 与survivor to的概念和s0与s1的概念。

2.1.3 复制算法

新生代采用的就是复制算法。当survivor from 内存用完,就将还活着的对象复制到另外一块survivor to上面。复制算法不会产生内存碎片。

新生代GC也是需要stop the world的,通常为几十毫秒。

2.2 老年代空间

在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代中。因此可以认为老年代中存放的都是一些生命周期较长的对象。

2.3 年龄

一个对象,每经历一次GC(minor GC 或 major GC),年龄就加一岁。
-XX:MaxTenuringThreshold=15
指定对象到达15岁时被移到Old区。默认值为15。
需要注意的是,并不是年龄非得到达指定值后才会被移到老年代,JVM还有自己的一套规则,烦人。
-XX:+PrintTenuringDistribution
这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。

2.4 vm参数

-Xmx //最大堆内存
-Xms //最小堆内存
-Xmn //新生代内存
示例:-Xms2048m -Xmx5120m
-XX:SurvivorRatio//新生代中,Eden区域与survivor区域的比值。默认为8。

2.5 常见错误

java.lang.OutOfMemoryError:java heap space
堆溢出。

3. 程序计数器

名为PC,Program Counter,是一个寄存器,存放该线程要执行的下一条语句的位置。
每个线程都有自己的PC,线程间不共享。

4.java虚拟机栈

每个线程都有自己的java虚拟机栈,线程间不共享。
每当进入一个函数时,创建栈帧(即Stack Frame,内含局部变量与函数出口等信息),入栈,函数执行完退出时,出栈。

4.1vm参数

-Xss  //每个线程的栈大小,默认为1M
示例: -Xss 2m

4.2 常见报错

java.lang.*Error
栈溢出。默认情况下函数嵌套达到2000层是没有问题的。可以认为调大栈空间。

5.本地方法栈

每个线程都有自己的本地方法栈,线程间不共享。
与java虚拟机栈类似,服务于本地(native)代码。
上一篇:配置Exchange OWA和Sharepoint网站单点登录


下一篇:Android性能调优篇之探索JVM内存分配