##虚拟机内存结构
###程序计数器 线程私有的,学过ARM或者汇编的同学应该很熟悉,表示的是当前线程执行到了哪一行字节码。
java虚拟机栈
“java虚拟机栈”这个名字很让人误会,看起来一点都不像是线程私有的,看起来像是“虚拟机”级别的东西,更像是线程共享的,但实际上它确实是线程私有的,所以我觉得它更应该叫做“线程栈”诸如此类更加“人如其名”的称呼。“java虚拟机栈”的生命周期是和线程相同的,线程执行某个方法的时候会为方法创建一个叫做“栈帧”的数据结构进行入栈,这个“栈帧”用来记录方法的局部变量等信息。“java虚拟机栈”深度是有限的,如果一个线程在调用方法数超过栈所能容纳的深度时候会出现StackOverflowError,告诉你栈爆了,怎么模拟这种情况呢,哈哈,执行没有递归终止条件的递归方法,如下:
public class App {
public static int f(int num) {
// 把递归终止条件去掉
// if(num>10){
// System.out.println("----->"+num);
// return num;
// }
num++;
return f(num);
}
public static void main(String[] args) {
f(0);
}
}
执行上述代码会出现StackOverflowError,如下:
本地方法栈
又是一个栈,还是本地的(native),容易想到这是一个与本地方法有关的栈,实际上确实如此,本地方法栈与java虚拟机栈发挥的作用是非常相似的,它们的区别在于虚拟机栈是为java方法服务,本地方法栈为本地方法服务,所以本地方法栈也是线程私有的。
java堆
java堆是线程共享的用来存储类实例和数组对象的(但不是唯一不能够类实例和数组对象)存储区域。java堆上的对象生命周期不一,有长有短,为了提高回收效率,采用了分代收集的策略。这里的“代”可以分为“新生代”、“老年代”
方法区
线程共享的用来保存系统的类信息(包括类的字段、方法、常量池、静态变量)的存储区域,方法区也叫永久代,这个是因为它不像java堆一样被Gc回收得那么频繁,但也不是说不能被回收,如果一个类不在被“引用”,这个类就应该从虚拟机卸载,被卸载的类是可以被回收的,如果系统的类太多的话也会导致方法去溢出。