java虚拟机(JVM)—内存模型
一.JVM内存结构
1.堆内存
堆内存主要用于存放java实例和数组等。堆内存在JVM启动时便会创建,随着应用程序运行的需要增大或减小。并且可以使用-Xms选项指定其大小。堆可以是固定大小或可变大小,具体取决于垃圾收集策略。如果程序运行需要的内存超过自动存储管理系统可用的堆内存,JVM就会会抛出OutOfMemoryError异常。
2.方法区内存
方法区内存也是在JVM启动时创建,用于存储数据结构,如:常量池,字段,函数等。非堆内存的默认最大大小为64 MB,也可以使用-XX:MaxPermSize 选项进行更改。如果方法区域中的内存无法满足分配请求,JVM也会抛出一个OutOfMemoryError异常。
3.栈内存
每个JVM线程都有一个与线程同时创建的私有堆栈,用于存储数据和部分结果,以及执行动态链接,返回方法的值以及分派异常。栈内存用于保存局部变量和部分结果,并在方法调用和返回中起作用。如果线程中的程序所需要的内存比JVM堆栈还大,则JVM就会抛出一个StackOverflowError(比如无限递归的时候)。
4.本地方法堆栈
本地方法堆栈也称为C堆栈; 它支持本其他语言编写的方法(比如JAVA通过JNA条用C语言编写的DLL时),通常在创建每个线程时按每个线程分配。
5.寄存器
该段内存用于存储当前正在执行的JVM指令的内存地址。每次创建新线程时都会创建一个程序计数器。程序计数器保持指向当前线程中正在执行的当前语句的指针。
二.JVM内存管理
1.新生代
新生代是创建所有新对象的地方,当新生代被填满时,进行垃圾回收。而新生代又分为三个部分,即:Eden Memory和两个Survivor Memory。大多数新创建的对象都位于Eden Memory中,
当Eden Memory空间充满对象时,执行Minor GC并将所有对象移动到Survivor Memory。
在GC的多个循环之后Survivor Memory里的对象会被移动到老年代中。通常是通过设置新生代中对象年龄阈值,然后才有会晋升到老年代。
2.老年代
当老年代内存用于存放多轮GC后长寿和存活的对象。通常垃圾收集在老年代内存中完成。老年代垃圾收集通常需要更长的时间。
3.永久代
永久代包含JVM描述应用程序中使用的类和方法所需的应用程序元数据,还包含Java库类和方法等。永久代对象在完整的垃圾收集时才被收集。