1 堆内存和非堆内存
JVM 内存划分为堆内存和非堆内存,堆内存分为年老代(Young Generation)、老年代(Old Generation),非堆内存就一个永恒代(Permanent Generation)。
年老代又分为 Eden 和 Survivor 区。Survivor 区由 FromSpace 和 ToSpace 组成。Eden 区占大容量,Survivor 两个区占小容量,默认比例是 8:1:1。
官网举荐新生代占堆的的 3 /8,Survivor 占新生代的 1 /10。
堆内存用处:寄存的是对象,垃圾收集器就是收集这些对象,而后依据 GC 算法回收。
非堆内存用处:永恒代,也称为办法区,存储程序运行时长期存活的对象,比方类的元数据、办法、常量、属性等。
在 JDK1.8 版本废除了永恒代,代替的是元空间(MetaSpace),元空间与永恒代上相似,都是办法区的实现,他们最大区别是:永恒代应用的是 JVM 的堆内存空间,而元空间应用的是物理内存,间接受到本机的物理内存限度。在前面的实际中,因为笔者应用的是 JDK8,所以打印出的 GC 日志外面就有 MetaSpace。
2 JVM 堆外部构型(新生代和老年代)
Jdk8 中曾经去掉永恒区,这里为了与时俱进,不再赘余。
上图演示 Java 堆内存空间,分为新生代和老年代,别离占 Java 堆 1 / 3 和 2 / 3 的空间,新生代中又分为 Eden 区、Survivor0 区、Survivor1 区,别离占新生代 8 /10、1/10、1/10 空间。
问题 1:什么是 Java 堆?
答复 1:JVM 标准中说到:”所有的对象实例以及数组都要在堆上调配”。Java 堆是垃圾回收器治理的次要区域,百分之九十九的垃圾回收产生在 Java 堆,另外百分之一产生在办法区,因而又称之为”GC 堆”。依据 JVM 标准规定的内容,Java 堆能够处于物理上不间断的内存空间中,然而逻辑上要求是间断的。
问题 2:为什么 Java 堆要分为新生代和老年代?
答复 2:以后 JVM 对于堆的垃圾回收,采纳分代收集的策略。依据堆中对象的存活周期将堆内存分为新生代和老年代。在新生代中,每次垃圾回收都有少量对象死去,只有大量存活。而老年代中寄存的对象存活率高。这样划分的目标是为了使 JVM 可能更好的治理堆内存中的对象,包含内存的调配以及回收。java 培训
问题 3:为什么新生代要分为 Eden 区、Survivor0 区、Survivor1 区?
答复 3:这是构造与策略相适应的准则,新生代垃圾收集应用的是复制算法(一种垃圾收集算法,Serial 收集器、ParNew 收集器、Parallel scavenge 收集器都是用这种算法),复制算法能够很好的解决垃圾收集的内存碎片问题,然而有一个人造的缺点,就是要就义一半的内存(即任意时刻只有一半内存用于工作),这对于贵重的内存资源来说是极度侈靡的。新生代在应用复制算法作为其垃圾收集算法的时候,对其做了优化,拿出 2 /10 的新生代的内存作为替换区,称为 Survivor0 区和 Survivor1 区(留神:有的博客上称为 From Survivor Space 和 To Survivor Space,这样论述也是对的,然而容易对初学者造成误导,因为在复制算法中,复制是双向的,没有固定的 From 和 To,这一次是由这一边到另一边,下次就是从另一边到这一边,应用 From Survivor Space 和 To Survivor Space 容易让起初学习者误以为复制只能从一边到另一边,当然有的博客中会附加不论从哪边到哪边,起始就是 From,起点就是 To,即 From Survivor Space 和 To Survivor Space 所对应的区循环对调,然而读者不肯定想的明确。所以笔者这里应用 Survivor0、Survivor1,缩小误会)
所以说,新生代在结构上分为 Eden 区、Survivor0 区、Survivor1 区,是与其应用的垃圾收集算法(复制算法)相适应的后果。
问题 4:对于永恒区 Permanent Space?
答复 4:因为 Jdk8 中勾销了永恒区 Permanent Space,本文为与时俱进,不再讲述 Permanent Space。