面试准备之java虚拟机内存结构

##虚拟机内存结构

###程序计数器 线程私有的,学过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堆上的对象生命周期不一,有长有短,为了提高回收效率,采用了分代收集的策略。这里的“代”可以分为“新生代”、“老年代”

上图结构可以看到,新生代可以分为Eden、Survivor,Survivor还分为From、to两部分,Survivor是存放年龄不大的对象,而Eden存放的是新生对象(PS:Eden是伊甸园的意思,亚当夏娃他们家,搞不懂为啥叫这名,这里姑且记住行了,不纠结!),而oldGen则相对好理解了,存放的是生命周期比较长的对象。看到这里你可能会有个疑问就是——“我创建一个对象怎么变成老生代的对象?”这里打个不太恰当的比方,如果一个人不要太短命,活过60岁被送敬老院,这时候我们说这个人是老年人了,而对象这个“身份”的转变过程也是有点相似的,结合下文例子就更加容易理解了:
新生代存放了大多数新生对象(注意是大多数,大对象可能直接往老年代里放,毕竟大对象回收再创建比较昂贵,伤不起!),From Survivor存放的是不至于老到变成老年代的对象,To Survivor则是还没使用的空间。假设此时来一次Minor Gc(指的是针对新生代的回收),演示如下: s

上图中打叉的矩形表示被回收对象,(a)表示Minor Gc的过程,(b)表示Minor Gc的结果,Eden中存活的对象复制到未使用Survivor,在被占用的Survivor里不够老的也复制到未使用的Survivor,而那些经过Minnor Gc 存活且足够老的则加入老年代,之后Survivor两部分(from、to)交换角色,而Eden则完全为空。

方法区

线程共享的用来保存系统的类信息(包括类的字段、方法、常量池、静态变量)的存储区域,方法区也叫永久代,这个是因为它不像java堆一样被Gc回收得那么频繁,但也不是说不能被回收,如果一个类不在被“引用”,这个类就应该从虚拟机卸载,被卸载的类是可以被回收的,如果系统的类太多的话也会导致方法去溢出。

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值