当前位置: 首页 > 后端技术 > Java

JVM堆内存和非堆内存

时间:2023-04-01 21:23:57 Java

1堆内存和非堆内存JVM内存分为堆内存和非堆内存。堆内存分为新生代和老年代。永久代(PermanentGeneration)。新生代分为Eden区和Survivor区。Survivor区域由FromSpace和ToSpace组成。Eden区占用容量大,Survivor区占用容量小。默认比例为8:1:1。官方建议新生代占heap的3/8,Survivor占新生代的1/10。堆内存使用:存储对象,垃圾回收器收集这些对象,然后按照GC算法回收。非堆内存使用:永久代,又称方法区,存放程序运行时长期存活的对象,如类的元数据、方法、常量、属性等。在JDK1.8版本中,永久代被废弃,取而代之的是MetaSpace。元空间类似于永久代,是方法区的实现。它们最大的区别在于永久代使用的是JVM的堆内存空间。元空间使用物理内存,直接受限于机器的物理内存。在下面的实践中,由于笔者使用的是JDK8,所以打印的GC日志中存在MetaSpace。2JVM堆的内部配置(新生代和老年代)Jdk8中已经去掉了永久区。为了与时俱进,这里不再赘述。上图是Java堆内存空间,分为新生代和老年代,分别占据Java堆空间的1/3和2/3。新生代分为Eden区、Survivor0区、Survivor1区,分别占新生代区的80%。/10、1/10、1/10个空格。问题一:什么是Java堆?答案1:JVM规范说:“所有对象实例和数组都必须在堆上分配”。Java堆是垃圾收集器管理的主要区域。百分之九十九的垃圾收集发生在Java堆中,另外百分之一发生在方法区,因此也被称为“GC堆”。根据JVM规范规定的内容,Java堆可以处于物理上不连续的内存空间,但逻辑上要求是连续的。问题二:Java堆为什么要分新生代和老年代?回答2:目前的JVM对堆垃圾回收采用分代回收策略。根据堆中对象的生命周期,堆内存分为新生代和老年代。在新生代中,每次垃圾回收都会有大量对象死亡,只有少量对象存活下来。老年代存储的对象存活率高。这样划分的目的是为了让JVM更好的管理堆内存中的对象,包括内存分配和回收。Java培训问题3:新生代为什么分为Eden区、Survivor0区、Survivor1区?答3:这是结构适应战略的原则。新生代的垃圾回收采用复制算法(一种垃圾回收算法,Serial收集器、ParNew收集器和Parallelscavenge收集器使用)。该算法可以很好的解决垃圾回收的内存碎片问题,但是它有一个天然的缺陷,就是牺牲一半的内存(即任何时候都只有一半的内存用于工作),极其为宝贵的内存资源而奢华。.当新生代使用复制算法作为其垃圾回收算法时,进行了优化,将新生代内存的2/10作为swap区,分别称为Survivor0区和Survivor1区(注:有些博客称之为FromSurvivorSpace和ToSurvivorSpace,这个解释也没错,但是容易误导初学者,因为在复制算法中,复制是双向的,没有固定的From和To,这次是从一侧到另一种,下一次是从另一边到这一边。使用FromSurvivorSpace和ToSurvivorSpace很容易让后来的学习者误以为只能从一侧复制到另一侧。当然有的博客会补充即不管从哪边到哪边,start开头是From,结尾是To,也就是FromSurvivorSpace和ToSurvivorSpace对应的区域循环是反的,但是读者可能看不懂。所以作者这里使用Survivor0和Survivor1是为了减少误解)所以,新生代的结构分为Eden区、Survivor0区、Survivor1区,这是适配它使用的垃圾回收算法(复制算法)的结果。问题四:关于永久空间?答4:由于Jdk8取消了PermanentSpace,本文为与时俱进,不再对PermanentSpace进行描述。