Java内存分配及垃圾回收算法(hotspot虚拟机) (3)

  为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。具体过程如下图所示:

Java内存分配及垃圾回收算法(hotspot虚拟机)

4.Generational Collection(分代收集)算法

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

  目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少。而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。

一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间(分别被命名为from和to),每次使用Eden空间和其中的一块Survivor空间。当触发一次YoungGC时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

三者内存大小比例为8:1:1

根据 IBM 公司对对象存活时间的统计,他们发现 80% 的对象存活时间都很短。于是他们将 Eden 区设置为年轻代的 80%,这样可以减少内存空间的浪费,提高内存空间利用率。



fen_dai

对象如何进入老年代?

1、大对象直接进入老年代
因为新生代是使用的复制算法,所以要尽量减少复制的内存,所以对象内存到一定的值后就会直接进入老年代。

2、新生代对象年龄到一定程度后进入老年代
每个对象会有一个Age的计数器,初始值为0,每经过一次GC并且存活,这个对象的Age就会加1,如果增加到一定程度(默认为15)。那么就会进入老年代中。

3、动态对象年龄判定
如果在新生代存活区中相同年龄所有对象大小的总和大于存活区的一半,年龄大于或等于该年龄的对象就会直接进入老年代。
比如现在存活区有三个对象,Age分别为2、2、3。那么Age为3的这个对象就会进入老年代。

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。


三. HotSpot虚拟机垃圾回收1. 什么是HotSopt虚拟机

Java HotSpot 虚拟机是 Java SE 平台的一个核心组件。它实现 Java 虚拟机规范,并作为 Java 运行时环境中的一个共享库来提供。作为 Java 字节码执行引擎,它在多种操作系统和架构上提供 Java 运行时设施,如线程和对象同步。它包括自适应将 Java 字节码编译成优化机器指令的动态编译器,并使用为降低暂停时间和吞吐量而优化的垃圾收集器来高效管理 Java 堆。它为分析、监视和调试工具及应用程序提供数据和信息。

它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。


2. 使用的垃圾回收算法

使用分代回收算法


3. 方法区和永久代的关系

永久代:在JDK8之前的HotSpot JVM,存放这些”永久的”的区域叫做“永久代(permanent generation)”。永久代是一片连续的堆空间,在JVM启动之前通过在命令行设置参数-XX:MaxPermSize来设定永久代最大可分配的内存空间,默认大小是64M(64位JVM由于指针膨胀,默认是85M)。

永久代存放内容: class文件中包括类的版本、字段、方法、接口等描述信息,还有运行时常量池(编译器生成的各种字面量和符号引用)

在Java虚拟机规范中,方法区在虚拟机启动的时候创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选择不在方法区实现垃圾回收与压缩。这个版本的虚拟机规范也不限定实现方法区的内存位置和编译代码的管理策略。所以不同的JVM厂商,针对自己的JVM可能有不同的方法区实现方式。

方法区和永久代的关系很像Java中接口和类的关系,类实现了接口,而永久代就是HotSpot虚拟机对虚拟机规范中方法区的一种实现方式。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzwsyw.html