一、分区介绍
- 每个线程:独立包括程序计数器、栈、本地栈
- 线程间共享:堆、堆外内存(方法区、永久代或元空间、代码缓存)
二、堆
- Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。(堆内存的大小是可以调节的)
- 在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除
- 堆空间,分为 4个部分
新生代(YoungGen):伊甸园区(Eden),幸存者0区(Survivor),幸存者1区(Survivor)
老年代(OldGen)
三、对象分配过程
- new的对象是分配在伊甸园区,
- 当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC), 此时用户线程就停止了(STW), 将伊甸园区没有任何指向性引用的对象进行销毁,回收空间。
- 剩下还在被占用的对象,就会复制到幸存者0区(并为每天对象分配年龄计数器。年龄+1)
- 此时伊甸园在次触发GC,同时会对幸存者1区的对象进行判断,还被占用的对象,从幸存者1区的对象复制到幸存者2区,年龄在+1,释放幸存者1区。被称为to区。幸存者0和幸存者1谁空了谁就是to区。 5. YGC存活的对象,会首先往to区放。同时对另一个幸存者区进行判断,没有被引用的就被回收,存活下来的年龄+1。当年龄计数达到15岁时晋升到老年代。15被称为默认情况的临界值,可以被修改。
- 老年代被回收的概率就小了, 当老年区内存不足时,再次触发GC:Major GC,进行养老区的内存清理。若养老区执行了Major GC之后发现依然无法进行对象的保存,就会产生OOM异常(内存溢出)。
** java.lang.OutOfMemoryError: Java heap space.**
-
扩展
-
老年代被GC,是新生代所花费的时间是10倍左右。
-
据统计分析80%左右的Java对象都是在新生代的过程中就被销毁掉了
(IBM公司的专门研究表明,新生代80%的对象都是“朝生夕死”的)
- 幸存者区满了的时候不会触发GC.只有伊甸园区满了的时候会和幸存者区一起被回收,
-
其他情况:
幸存者区满了,伊甸园区的对象也有可能晋升到老年代。
大的对象直接被晋升到老年代。
新生代:老年代 == 1:2
伊甸园区(Eden), 幸存者0区,幸存者1区 == 8:1:1


- 在hotSpot中,Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1(测试的时候是6:1:1),开发人员可以通过选项 -XX:SurvivorRatio 调整空间比例,如-XX:SurvivorRatio=8
四、方法区 Method Area(元空间)
- 方法区可以看作是一块独立于Java堆的内存空间
- 方法区与Java堆一样,是各个线程共享的内存区域
- 方法区主要存储 类信息,常量,静态变量。
java.lang.OutOfMemoryError: Metaspace
网友评论