堆内存

堆内存区域划分
Java中的堆是JVM所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
在Java中,堆被划分成两个不同的区域:新生代 ( Young,年轻代 )、老年代 ( Old )。
新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
以下都是基于JDK1.6版本
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),
即:新生代 ( Young ) = 1/3 的堆空间大小,老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Eden : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),
即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。
JVM堆内存解释一
大部分对象创建都是在Eden的
(除了个别大对象外,大对象内存可以设置参数【-XX:PretenureSizeThreshold=字节数】配置,
超过配置内存的大对象直接进入老年代,from和to不是固定的(可以互换身份,Survivor区),
初始化的时候其中一个是空的。新生代的 Minor GC 中,一个Survivor区中数据复制进去,另个是空的,下一次GC的时候,有数据的是from Survivor,没数据的to Survivor,GC的时候,from区和Eden区的数据都复制到to中。这样from和to就互换身
份,一直这么循环处理。第2步中复制一次,所有对象年龄加1,当任意一个对象复制到一定次数(默认15次,
可以配置【-XX:MaxTenuringThreshold=数字】参数进行修改)的时候,就被复制到了老年代
JVM堆内存解释二
大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 from或者 to,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度
(默认为 15 岁),就会被晋升到老年代中。
元空间,永久代,方法区之间的关系
个人理解:元空间和永久代只不过是方法区的实现,即方法区是规范的名字,元空间和永久代是hotspot虚拟机
独有的,元空间是新版本出现的,替代了永久代,永久代并不在堆内存中,而是在JVM内存中,受到JVM内存的限
制,而元空间是在本地内存中,只受到本机实际内存限制。
永久代是Hotspot虚拟机特有的概念,是方法区的一种实现,别的JVM都没有这个东西。在Java 8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间。
永久代或者“Perm Gen”包含了JVM需要的应用元数据,这些元数据描述了在应用里使用的类和方法。
注意:永久代不是Java堆内存的一部分。永久代存放JVM运行时使用的类。永久代同样包含了Java SE库的类和方
法。永久代的对象在full GC时进行垃圾收集。
- 整个永久代有一个 JVM 本身设置固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内
存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。 - 你可以使用**-XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系
统内存的限制。-XX:MetaspaceSize 调整标志定义元空间的初始大小**,如果未指定此标志,
则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。 - 元空间里面存放的是类的元数据,这样加载多少类的元数据就不由 MaxPermSize**(永久代最大大小)**控制了,
而由系统的实际可用空间来控制,这样能加载的类就更多了。
垃圾收集器GC收集标准
在java语言中,判断一块内存空间是否符合垃圾收集器收集标准的标准只有两个:
给对象赋值为null,以下没有调用过。
给对象赋了新的值,重新分配了内存空间。