您的位置:首页 > 其它

JVM运行时内存空间结构

2013-05-24 11:32 441 查看
JVM执行Java程序的过程中管理的内存空间,包括下列几个区域:

程序计数器(Program CounterRegister)

· 线程私有,占用空间很小。

· 线程所执行代码行号指示器。

· 解释器通过计数器的值选择下一条执行的字节码指令。

· 线程执行Native方法时值为空。

· 没有OOM(OutOfMemory)。Java虚拟机栈(Java
Virtual Machine Stacks)

· 线程私有。· 储存方法栈帧(Stack
Frame)。

· 栈帧:储存局部变量表、操作栈、动态链接、方法出口等。

· 局部变量表:编译器可知的基本类型、对象引用和returnAddress(字节码指令的地址)。在编译期间完成分配,运行时大小不变。

· 存在StackOverflowError和OOM。

· StackOverflowError:线程请求栈深度大于VM允许深度。

· OOM:创建线程或扩展线程空间时无足够内存。

StackOverflowError例子:

[align=left]/**[/align]
[align=left]* -Xss256k[/align]
[align=left]*[/align]
[align=left]* @author Alfred Xu <bjxufeng@360buy.com>[/align]
[align=left]*[/align]
[align=left]*/[/align]
public class StackSOF
{
[align=left] int recursionLength;[/align]
[align=left][/align]
void recusion()
{
[align=left] recursionLength++;[/align]
[align=left] recusion();[/align]
[align=left] }[/align]
[align=left][/align]
public static void main(String[]
args) {
[align=left] StackSOF sof = new StackSOF();[/align]
[align=left] try {[/align]
[align=left] sof.recusion();[/align]
} catch (Throwable
e) {
[align=left] System.out.println(sof.recursionLength);[/align]
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]

OOM例子:

[align=left]/**[/align]
[align=left]* -Xss2m[/align]
[align=left]*[/align]
[align=left]* @author Alfred Xu <bjxufeng@360buy.com>[/align]
[align=left]*[/align]
[align=left]*/[/align]
public class StackOOM
{
static class Tester extends Thread
{
[align=left] @Override[/align]
public void run()
{
[align=left] try {[/align]
Thread.sleep(1000
* 1000);
} catch (InterruptedException
e) {
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left][/align]
public static void main(String[]
args) {
for (int i
= 0;; i++) {
[align=left] new Tester().start();[/align]
[align=left] System.out.println(i);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]

本地方法栈(Native MethodStacks)

· 线程私有,类似虚拟机栈。

· 服务Native方法。

· 同样存在StackOverflowError和OOM。

· Hotspot中将Java虚拟机栈和本地方法栈合二为一,通过-Xss设置大小。JDK1.6以前默认256K,1.6默认1M。

Java堆(Java Heap)

· 所有线程共享。

· 储存对象实例。

· GC和OOM的主要区域。

Heap OOM例子:

[align=left]/**[/align]
[align=left]* -Xms10m -Xmx10m[/align]
[align=left]*[/align]
[align=left]* @author Alfred Xu <bjxufeng@360buy.com>[/align]
[align=left]*[/align]
[align=left]*/[/align]
[align=left]public class HeapOOM {[/align]
public static void main(String[]
args) {
List<Long> list
= new ArrayList<Long>();
for (long i
= 0;; i++) {
[align=left] list.add(i);[/align]
[align=left] System.out.println(i);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]

方法区(Method Area)

· 又叫非堆(Non-Heap),对应HotSpot的永久代(Permanent
Generation)。

· 所有线程共享。

· 储存VM加载的类信息、常量、静态变量、JIT编译代码等。

· 也有OOM,一般是由于大量使用反射生成class。

· 包含运行时常量池(Rumtime ConstantPool)。

常量池溢出例子:

[align=left]/**[/align]
[align=left]* -XX:MaxPermSize=1m[/align]
[align=left]*[/align]
[align=left]* @author Alfred Xu <bjxufeng@360buy.com>[/align]
[align=left]*[/align]
[align=left]*/[/align]
public class ConstantPoolOOM
{
public static void main(String[]
args) {
List<String> list
= new ArrayList<String>();
for (int i
= 0;; i++) {
[align=left] list.add(String.valueOf(i).intern());[/align]
[align=left] System.out.println(i);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]

本机直接内存(Direct Memory)

· 不受VM直接管理,但也有OOM。

· 和NIO中的DirectByteBuffer相关。

· 默认和Java堆大小一致。

例子:

[align=left]/**[/align]
[align=left]* -XX:MaxDirectMemorySize=10m[/align]
[align=left]*[/align]
[align=left]* @author Alfred Xu <bjxufeng@360buy.com>[/align]
[align=left]*[/align]
[align=left]*/[/align]
[align=left]@SuppressWarnings("restriction")[/align]
public class DirectMemoryOOM
{
static final int _1MB =
1024 * 1024;
[align=left][/align]
[align=left] static void unsafeAllocate() throws IllegalArgumentException,[/align]
IllegalAccessException
{
Field unsafeField
= Unsafe.class.getDeclaredFields()[0];
[align=left] unsafeField.setAccessible(true);[/align]
Unsafe unsafe =
(Unsafe) unsafeField.get(null);
List<Long> list
= new ArrayList<Long>();
for (int i
= 0;; i++) {
long l
= unsafe.allocateMemory(_1MB);
[align=left] list.add(l);[/align]
[align=left] System.out.println(i);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left][/align]
static void byteBufferAllocate(boolean direct)
{
List<ByteBuffer>
list = new ArrayList<ByteBuffer>();
for (int i
= 0;; i++) {
[align=left] ByteBuffer bb;[/align]
if (direct)
{
[align=left] bb = ByteBuffer.allocateDirect(_1MB);[/align]
[align=left] } else {[/align]
[align=left] bb = ByteBuffer.allocate(_1MB);[/align]
[align=left] }[/align]
[align=left] list.add(bb);[/align]
[align=left] System.out.println(i);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left][/align]
public static void main(String[]
args) throws IllegalArgumentException,
IllegalAccessException
{
[align=left] byteBufferAllocate(true);[/align]
//
unsafeAllocate();
[align=left] }[/align]
[align=left]}[/align]

Hotspot Java内存空间结构



新生代(Young Generation)

大部分的对象的内存分配和回收在这里完成。

Eden

新建的对象分配在此,minor GC后被清空。

Survivor

存储至少经过一次GC存活下来的对象,以增大该对象在提升至老生代前被回收的机会。

From Space

在minor GC后被清空,GC后存活的对象放入老生代。

To Space

Eden中在新生代GC后存活的对象放在此。

老生代(Old Generation)

多次GC后存活的对象或者新生代放置不下的大对象。

永生代(PermanentGeneration)

方法区。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: