Jvm -堆对象的划分

堆对于一个jvm进程来说是唯一的,一个进程只有一个jvm,但是进程半酣多个线程,多个线程共享一个堆。

也就是说,一个jvm实例只存在一个堆,同时对也是Java内存管理的核心区域。

Java堆区域的大小在jvm启动时就已经被确定下来了,是jvm管理的最大的一块内存空间,但对的大小也是可以调节的。

《Java虚拟机规范》规定对可以处于物理上不连续的内存空间中,但在逻辑上他应该被视为是连续的。
所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区,在《Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组对象都应当在运行时分配在堆上。数组共和对象永远不可能储存在栈上,因为栈中保存引用的地址,这个引用会指向对象或者数组在堆中的位置。

在方法结束后,堆中 的对象并不会被马上移除,仅仅是在垃圾回收时才会被移除。对GC指向垃圾回收的重点区域。

在Java1.7之前堆内存在逻辑上分为:新生代+养老区+永久区
● 新生区 又被划分为Eden区和Survivor区
● 养老区
● 永久区
Jvm -堆对象的划分_第1张图片

在Java1.8后分为:新生区+养老区+元空间
●新生区 Young/New 又被划分为Eden区和Survivor区
● 养老区
● 元空间
Jvm -堆对象的划分_第2张图片
年轻代与老年代
在jvm中存储的对象可以被划分为两类:

  1. 一类是生命周期较短的瞬时对象,之类对象的创建消亡都非常迅速
  2. 另一类对象的生命周期却非常长,在某些极端的情况下还能够与jvm的上明周期保持一致

Java堆区进一步细分的化还可以划分为YoungGen年轻代和OldGen老年代
其中年轻代又可以划分为Eden空间、Survivor0和Survivor1空间也叫做from、to区
Jvm -堆对象的划分_第3张图片
那么对象是如何进行分配的呢?
为对象分配内存是意见非常严谨和复杂的任务,jvm的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑GC完成垃圾回收后在内存空间产生的内存碎片。

  1. new的对象先放到Eden也就是伊甸园区,此区域有大小限制
  2. 当伊甸园区的空间被填满时,程序还在创建新的对象,jvm的垃圾回收器将对伊甸园进行垃圾回收(MinorGc),将伊甸园中不在被其他对象所引用的对象进行回收,再将新家在的对象放入到伊甸园区
  3. 之后将伊甸园中剩余的对象移动到s0区
  4. 如果再次触发垃圾回收,此时上次幸存下来的放到s0区的,如果没有被回收就会被放到s1区
  5. 如果再次经历垃圾回收,此时会从新放回s0区,接着再去s1区
  6. 进入养老区的次数默认是15次
  7. 在养老区,相对悠闲.当养老区的内存不足时,再次触发Gc(MajorGc)进行养老区的内存清理
  8. 若在养老区执行了MajorGc之后发现依旧无法进行对象的保存就会报oom异常
    ● 针对幸存者s0,s1区的总结:复制之后有交换,谁空谁是to
    ● 关于垃圾回收:频繁在新生区收集,很少在老年代收集,几乎不再永久代和元空间进行收集

你可能感兴趣的:(jvm,后端,jvm,java,算法)