JAVA 内存区域及使用分配 - 实战 JVM(一)

878
原文链接: www.begincode.net

介绍JAVA虚拟机运行时内存区域划分,使用分配

JAVA内存区域及使用分配-实战JVM(一)


JAVA虚拟机运行时会将JVM使用的内存划分为不同的区域,每个区域负责不同的功能,以及各个区域的创建,销毁都各不相同。

下图是JVM运行时内存数据区的划分,


图1、JVM运行时数据区

1、程序计数器

    每个线程都拥有一个独立的程序计数器,用于记录当前线程所要执行的字节码指令,该类内存区域为“线程私有”内存。

2、虚拟机栈

   该区域也有人称为栈内存(对应java堆内存),这个叫法不完全正确,但可以便于理解。

   该区域也是线程私有的,并且与线程的生命周期相同。

   主要负责方法执行的内存部分,在每个方法执行时都会创建一个栈针,同时存储局部变量,操作数等方法相关信息。

   局部变量表存储内容:主要是基本数据类型和对象的引用,而对象本身存储在堆中

   每一次方法的调用到完成,都对应一个栈针在虚拟机栈中出入栈的过程。

   该区域会抛出stackOverFlowError和OutOfMemoryError错误

   stackOverFlowError 是线程请求的栈深度大于虚拟机允许的深度,如下面的代码

	public static void main(String[] args) {
		testStackOverFlow();
	}
	public static void testStackOverFlow(){
		System.out.println("stackOverFLow");
		testStackOverFlow();
	}

OutOfMemoryError错误就是栈空间溢出,比如局部变量过多,占用内存过大,都会产生就不举例说明

3、本地方法栈

    和虚拟机栈类似,只是负责本地Native方法,也会抛出stackOverFlowError和OutOfMemoryError错误,如IO中常用的文件读写操作的Native方法,可能是C语言或者其他语言的实现。

4、JAVA堆(JAVA Heap),GC堆

   JAVA堆是JAVA虚拟机管理的内存,最大,最重要的部分,是所有线程共享的区域,

    也是GC(垃圾回收)的主要回收部分,

    再进行划分可以分为新生代,老生代(老年代);新生代可以划分为:Eden,From Survivor,To Survivor 

    主要存放对象实例,可以通过配置,设置不同代的大小和垃圾回收策略,很多优化也在堆上进行实现。

    堆的详细介绍:www.begincode.net/blog/47

    该区域会抛出 OutOfMemoryError异常

5、方法区(Method Area),非堆,永久代

   该区域也是线程共享的内存区域,该区域也会进行垃圾回收,但可以忽略不计,因为效果很难令人满意

   主要存储虚拟机加载的类信息,常量,静态变量等

   该区域会抛出OutOfMemoryError异常,主要是启动时需要加载的类,常量,静态变量等信息特别多,超过了该区域设置的内存空间,就会抛出异常,

  可以看看eclipse内存设置,如果将内存设置特别小就会抛出该内存溢出异常

  www.begincode.net/blog/50

   运行时常量池:属于方法区的一部分,主要存储运行时常量,如String的intern方法产生的字符串常量。

6、直接内存

    直接内存没有在图中显示,以为他并不是虚拟机运行时数据区的一部分,不归虚拟机管理,但该内存区域也会出现OutOfMemoryError异常,

   该区域使用主要是在NIO的缓冲区的使用,会用到系统直接内存,因为是通过本地方法分配的内存,当本机无法分配更多的内存时就会抛出内存溢出异常