Java内存模型——创建对象在堆区如何分配内存

一、程序运行时的区域划分

        与c/c++程序不同,在运行Java程序时,内存的控制权是交给JVM管理的,而JVM在运行Java程序时会把内存划分为若干个不同的数据区域——线程共享区域和线程私有区域,其中:

        线程私有区域分为虚拟机栈、本地方法栈和程序计数器;

        线程共享区域在JDK1.8之前分为 Heep 堆区 和 Method Area 方法区,在JDK1.8之后分为 Heep堆区 和 MetaSpace元空间。

二、Heep堆区

        Heep堆区是JVM管理的内存中最大的一块区域,堆区被所有线程所共享,一般程序中创建的对象、数组都会在堆区分配内存。也是垃圾回收器GC管理的主要区域。因为目前垃圾回收算法都采用分代垃圾收集算法,所以堆区也进行了分代划分:新生代和老年代,其中新生代占整个堆区内存的1/3,老年代占整个堆内存的2/3。

      

        新生代又划分为Eden区和两个Survivor幸存者区from、to(有的叫法称为s0、s1) 一般新创建的对象会被放在这里,Eden区占整个新生代区的8/10,from和to分别各占1/10。

 三、创建对象时的内存分配

创建一个新对象时:

        首先会在Eden区中分配空间,若内存空间足够,则为该对象分配内存;

        当Eden中内存不足时,会执行一次YGC(minor GC)回收没有被引用的对象,将被引用的对象(未被回收的对象)存入from幸存者区,此时再判断Eden区的内存是否足够,足够则分配内存;

        不足,则判断老年代是否放得下,若放得下则在老年代为该对象分配内存;

        若老年代还放不下,则会执行FGC(major GC)清理堆区垃圾(未被引用的对象),结束后再判断是否能存下,能,则在老年代分配内存;

        否则会OOM(OutOfMemoryError),产生堆内存溢出错误。

PS:下面详细讲讲YGC的过程

        执行YGC时,是将Eden区中存储的旧对象实行清楚策略,把那些没有被引用的对象视为"垃圾",然后清除,剩余被使用的对象(未被清理)若from幸存者区存的下,则会被放入幸存者区,若这些未被清理的旧对象过大,则会被直接放入老年代。

        当下一次执行YGC时,存放在from幸存者区的对象若还未被清理,该对象对象头中的age+1,则会连同本次从Eden区中幸存的对象一起被存入to幸存者区(下一次YGC后的幸存者又会被挪入from区,可以理解为from和to交替使用,总有一个是空的),同样,若放不下,则会直接存入老年代。以此类推,当对象的年龄>15时,也会从幸存者区拿出放入老年代。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值