运行时数据区通常包括这几个部分:
一 线程私有内存区:编译时确定大小
1 Java栈(VM Stack):存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。
2 本地方法栈(Native Method Stack):本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。
3 程序计数器(Program Counter Register):存放执行哪条指令
二 线程共享内存区:
4 方法区(Method Area):存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
也被称为非堆区域(在HotSpot JVM的实现当中)
它被分为两个主要的子区域:
持久代 —— 这个区域会存储包括类定义,结构,字段,方法(数据及代码)以及常量在内的类相关数据。它可以通过-XX:PermSize及-XX:MaxPermSize来进行调节。如果它的空间用完了,会导致java.lang.OutOfMemoryError: PermGen space的异常。
代码缓存——这个缓存区域是用来存储编译后的代码。编译后的代码就是本地代码(硬件相关的),它是由JIT(Just In Time)编译器生成的,这个编译器是Oracle HotSpot JVM所特有的。
5 堆(Heap):存储对象本身和数组
堆被分为:
Eden区 —— 新对象或者生命周期很短的对象会存储在这个区域中,这个区的大小可以通过-XX:NewSize和-XX:MaxNewSize参数来调整。新生代GC(垃圾回收器)会清理这一区域。
Survivor区 —— 那些历经了Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域。这个区的大小可以由JVM参数-XX:SurvivorRatio来进行调节。
老年代 —— 那些在历经了Eden区和Survivor区的多次GC后仍然存活下来的对象(当然了,是拜那些挥之不去的引用所赐)会存储在这个区里。这个区会由一个特殊的垃圾回收器来负责。年老代中的对象的回收是由老年代的GC(major GC)来进行的。
http://www.cnblogs.com/dolphin0520/p/3613043.html
http://ifeve.com/jvm-permgen-where-art-thou/
https://blog.csdn.net/ns_code/article/details/17565503
http://www.cnblogs.com/sunada2005/p/3577799.html