垃圾收集与内存分配算法

3.1判断对象是否已死引用-计数算法

给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器为0的对象就是不可能再被使用的。

3.2判断对象是否已死引用-可达性分析算法

在主流的程序语言中,都是通过可达性分析来判断对象是否存活的。这个算法的基本思路就是通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象至GC Roots没有任何引用链相连时,则证明此对象不可用。

在java语言中,可作为GC Roots的对象包括下面几种:

虚拟机栈中引用的对象

方法区中类静态属性引用的对象

方法区中常量引用的对象

本地方法栈中JNI引用的对象

3.3标记-清除算法

最基础的收集算法是“标记清除”算法,如同它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

3.4复制算法

为解决效率问题,一种称为“复制”的收集算法出现了,它将可用内存按容量划分为大小相等的现块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

3.5标记-整理算法

根据老年代的特点,有人提出了另一种“标记-整理”算法,标记过程仍然与“标记-清除”算法一样,但后继步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。

4、垃圾收集器

4.1Serial收集器

新生代收集器,这个收集器是一个单线程的收集器,它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

4.2ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾之外,其余行为都相同。

ParNew收集器也是使用-XX:+UseConcMarkSweepGC选项后的默认新生代收集器,也可以使用-XX:+UseParNewGC选项来强制指定它。在cpu非常多的情况下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

4.3Parallel Scavenage收集器

Parallel Scavenage收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。

Parallel Scavenage收集器的目标是达到一个可控制的吞吐量。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

Parallel Scavenage收集器提供了两个参数用于精确控制吞吐量,分别控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。

Parallel Scavenage收集器还有一个参数-XX:UseAdaptiveSizePolicy,当这个参数打开之后,就不需要手工指定新生代的大小、Eden与Survivor的比例等参数了。

4.4Serial Old收集器

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。

4.5ParallelOld收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。

4.6CMS收集器

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。

CMS收集器是基于“标记-清除”算法实现的,它的动作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

1、初始标记,2、并发标记,3、重新标记,4、并发清除

其中初始标记、重新标记这两个步骤仍然需要“Stop TheWorld”。

CMS收集器有3个缺点:

1、对Cpu资源非常敏感,2、无法处理浮动垃圾,3、会有大量空间碎片产生。

4.7G1收集器

G1具备如下特点:1、并行与并发,2、分代收集,3、空间整合,4、可预测的停顿。

使用G1收集器时,Java堆的内存布局就与其他收集器有很大的差别,它将整个Java堆划分为多个大小相等的独立区域,虽然还保留有新生代和老年代的概念,但新和代和老年代不再是物理隔离的了,它们都是一个部分Region的集合。

G1收集器的动作大致分为以下几个步骤:

1、初始标记,2、并发标记,3、最终标记,4、筛选回收

时间: 2024-10-12 20:55:47

垃圾收集与内存分配算法的相关文章

MINI3内存分配算法

1 最差适应算法 2 #ifdef USING_WORST_FIT 3 { 4 //先找到第一个满足要求的空洞, 5 //再以第一个为标准寻找最适合的空洞. 6 //当最适合的空洞完全吻合 7 //就直接划给它,当空洞较大时就切割. 8 9 //首先注册目标指针.目标前一个指针.头指针 10 //记录目标大小和目前最适合大小 11 register struct hole *hp; 12 register struct hole *prevAim_ptr; 13 register struct

垃圾收集与内存分配

垃圾收集的位置 JVM把内存区域分为多个子区.在这些子区中,程序计数器,虚拟机栈和本地方法栈生命周期与线程绑定,程序计数器始终指向当前执行的字节码位置,或为空,虚拟机栈和本地方法栈则随着方法的执行和结束执行如栈和出栈操作,每一个栈帧的内存大小在类结构确定下来时就为已知的,因此在这些子区中的内存分配和回收都具有确定性,因此后文讨论的“内存”主要指堆和方法区. 哪些可以回收 当内存不足需要回收时,首先要判断哪些内存可以回收.之前在学习Java时,我一直以为JVM是靠引用计数来判断对象是否已死,但实际

操作系统: 最佳适配算法和邻近适配算法的模拟实现(内存分配算法)

实现动态分区的分配算法. (1) 最佳适配算法:选择内存空闲块中最适合进程大小的块分配. (2) 邻近适配算法:从上一次分配的地址开始查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程. 模拟添加进程的时候,假定内存是一块完整的空闲区,对于算法(1)来说,分配的时候遍历所有的空闲内存块,找出其中最适合的一块,注意此时内存分区的总块数可能已经发生了变化: 对于算法(2)来说,则需要从上次分配的内存块(使用变量记录即可)接着向下找到第一个满足条件的块即可,内存分区的总块可能也已经发生了变

内存分配算法 之 首次适应-最佳适应

程序在向操作系统申请内存空间的时候,操作系统会扫描空闲块链表并从中取出一块足够大的分配,与之对应的算法有 首次适应 和 最佳适应,顾名思义,首次适应就是把首次遇到的足够大的空闲块分配给应用程序,最佳适应就是扫描完空闲块链表把大小与申请空间最匹配的空闲块分配给应用程序. mem.h        程序用到的头文件 main.c       主函数 fit.c        具体的实现函数 这里使用make来编译使用,若是读者还没接触过make的, 请移步参考我写的这篇文章:http://netca

我所理解的内存分配算法(一)

内存分配从本质上来说是一种空间管理算法,给你一块连续的空间,提供存储服务,那么你的空间管理跟分配要采用什么样的算法才会比较高效? Bump-the-Pointer Bump-the-Pointer是最简单的算法.HotSpot的MM白皮书是这么描述btp的, That is, the end of the previously allocated object is always kept track of. When a new allocation request needs to be s

内存分配---FF、BF、WF三种算法

动态分区分配是根据进程的实际需要,动态的为之分配内存空间.而在实现可变分区分配时,将涉及到分区分配中 所用的数据结构.分区分配算法和分区的分配与内存回收的过程. 分区分配中的数据结构:(1)描述空闲块的数据结构.(2)内存块的描述. #define PROCESS_NAME_LEN 32 //进程名长度 #define MIN_SLICE 10 //最小碎片的大小 #define DEFAULT_MEM_SIZE 1024 //内存大小 #define DEFAULT_MEM_START 0 /

JVM-垃圾收集器与内存分配策略

1.叙述的问题 对象什么时候死亡? 垃圾收集算法 垃圾收集器 内存分配与回收策略 2.GC需要完成的三件事: 哪些内存需要回收? 什么时候回收? 怎么回收? 1)判断对象死亡的方法: 引用计数器算法:给对象中添加一个计数器,每当有一个地方引用它时,计数器加1:当引用失效时,计数器减1:任何时刻计数器都为0的对象就是不可能再被使用的. 根搜索算法:通过一系列的名为"GC Roots"的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链, 当一个对象到GC Roots没有任何

理解JVM之GC&内存分配

垃圾回收机制 对象存活判定算法 垃圾收集算法 HotSpot算法实现和垃圾收集器 内存分配和回收策略 对象存活判定算法(JVM回收那些对象) 概念:四种引用类型 强引用:及时内存不足也不会被GC,不会随意回收强引用对象:即使抛出OOM(OutOfMemoryError),也不会随意回收强引用对象 软引用:只有内存不足时,会被GC:回收后内存不足会抛出OOM异常 弱引用:无论当前内存是否充足都会被GC 虚引用:任何时候都会别GC a.引用计数算法:给对象添加一个引用计数器,每当有一个地方引用他的时

SQLite剖析之动态内存分配

SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.以及保存查询结果.我们做了很多努力来让SQLite的动态内存分配子系统可靠.可预测.健壮并且高效.本文概述SQLite的动态内存分配,软件开发人员在使用SQLite时可以据此获得最佳性能. 1.特性    SQLite内核和它的内存分配子系统提供以下特性:    (1)对内存分配失败的健壮处理.如果一个内存分配请求失败(即malloc()或realloc()返回NULL),SQ