JVM的运行时数据区、JMM、Java对象的内存布局

JVM的运行时数据区

下图是根据orcle官网做的简图。在这里插入图片描述

1. 方法区

	所有线程共享的区域。
	存放类的静态变量、常量、类的结构信息
	如果内存不足时,会报错OOM

2. 堆

	所有线程共享区域。
	存放的是对象或者数组
	如果内存不足时,会报错OOM

3.Java虚拟机栈

	是线程独享的区域。
	再调用方法的时候,栈帧会进行压栈。栈的特性是先进后出。
	如果内存不足时,会报错StackOverError
	一下代码表示 t1调用t2方法,其中t2又调用t3方法。其压栈为
	t1(){ t2();}
	t2() {t3();}
	t3(){}
	t1进栈,条用t2的时候t2栈帧进栈,t2调用t3的时候,t3栈帧进栈。 t3执行完后,t3栈帧出栈,
	然后t2出栈,然后t1出栈。
	执行完成。

	提问:
	如果将栈设置的很大: 虽然会减少stackOverFlow 但是会直接限制线程创建的数量。
		一个 t1有个虚拟机栈  t2也有个虚拟机栈。由于cup的资源有限,所以线程的创建数量会减少
	如果将栈设置的很小: 就能经常性的栈溢出

4.PC寄存器

	每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存
	有当前正在执行的JVM指令的地址。
	每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。保存下一条将要执行的指令地址的
	寄存器是 :PC寄存器。
	PC寄存器的内容总是指向下一条将被执行指令的地址,这里的地址可以是一个本地指针,
	也可以是在方法区中相对应于该方法起始指令的偏移量。

5.本地方法栈

	本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法

JMM(虚拟机的物理内存)

在运行时数据区中 栈内存的生命周期是和线程的生命周期相同的。 但是方法区和堆内存是进程的生命周期相同。
相当于:堆内存和方法区数据物理内存。在创建进程的时候就已经存在了。在JMM中方法区也称为metaspace;
内存模型如下图
在这里插入图片描述

内存区域的存在意义

  • Old区和Yong的诞生

		如果所有的对象都放入堆内存的时候,当堆内存空间不足的时候,将进行垃圾回收。
		比如堆内存是2G的空间。所以每次垃圾回收都要扫描2G的数据,这样特别影响性能。
		所以又将堆内存分为了Old区(老年代)和Yong区(新生代);
		
		Old区存放对象信息是: 被垃圾回收次数超过15次的  或者对象特别大的
  • Yong区继续优化为 Eden区和Survive区

	比如Yong区有9个为1M的对象,分别标号为1-9,经过垃圾回收后,有可能回收的是其中的任何一个标号。
	如果  147。如果此时,有进来一个大小3M的对象,由于 1 4 7 位置不是连续的,
	所以无法将3M的对象放到Yong区。 因此将 Yong区分为 Eden区 和Survive区。
	
	对象进来先在Eden区分配空间。 当进行垃圾回收后,幸存的并且年龄小于15岁的对象会移至Survive区。
	这样就可以保证Eden区的空间是连续的了。 
	垃圾回收的时候是整个Yong区,所以Eden和Survive区都要进行垃圾回收。
  • Survive区继续优化为S0(From)和S1(To)两个相等的区

	同理,Survive区也存在空间碎片的问题。 因为,Survive区有9个为1M的对象,分别标号为1-9,
	进行垃圾回收后,回收了 1 4 7。但是从Eden区中幸存下来一个3M的对象,这时的Survive空间明明足够,
	但是由于1 4 7空间的不连续,导致无法给这个3M的对象分配空间。	所以将Survive区平均分为两个空间。
	S0区和S1区。 
	S0或者S1其中的某一个区域一定是为空的。
	比如S0有对象,经过垃圾回收后,Eden区幸存下来的对象移动到S1区,S0区幸存的对象也被移动到S1区。
	这样S0区就为空了。下次垃圾回收,S0区存放幸存对象,S1为空。
	虽然浪费了10%(Eden区默认的分配比例时811)一些空间,但是解决了空间碎片的问题。
	
	如果S0/1区万一不够用,就跟老年代借点空间。【担保机制】,如果S0/1的对象年龄大于15岁,
	则存放到老年代。

Java对象的内存布局

Java对象内存布局是指 Java的每个对象中包含哪些内容。
在这里插入图片描述
以上是对模型的总结。。。。。。。。。。。。。。

自问自答

  • (1)如果S0/1区万一不够用怎么办?
	老年代借点空间。【担保机制】,如果S0/1的对象年龄大于15岁,则存放到老年代。
  • (2)如果将栈设置的很大或者 很小会有什么问题?
	如果将栈设置的很大: 虽然会减少stackOverFlow 但是会直接限制线程创建的数量。 
	一个 t1有个虚拟机栈  t2也有个虚拟机栈。由于cup的资源有限,所以线程的创建数量会减少
	如果将栈设置的很小: 就能经常性的栈溢出
  • (3)Yong区比例默认8:1:1的原因
	Yong区包含Eden区 S0  S1区。其中S0和S1区的大小必须一致,这样才能保证完美的复制。 
	Eden设置的比较大的原因是:因为大多数的对象的生命周期很短,基本上就是‘朝生夕死’的。
	所以尽可能的让对象在Eden区自生自灭,不再做移至S区的动作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值