用于垃圾回收的并行标记处理方法及装置与流程

文档序号:11216193阅读:729来源:国知局
用于垃圾回收的并行标记处理方法及装置与流程

本申请涉及计算机技术领域,尤其涉及一种用于垃圾回收的并行标记处理方法及装置。



背景技术:

垃圾回收(即garbagecollection简称gc)技术被广泛使用在当今流行的许多高级语言虚拟机中。gc技术根据垃圾收集器(简称collector)和宿主(简称mutator)的关系可以分为两种:collector工作时mutator暂停(简称stop-the-world-gc即stw-gc),collector工作时mutator不暂停(简称并发gc即concurrent-gc)。目前完全并发gc还没有哪一款虚拟机真正实现,流行的高级语言虚拟机比如jvm,v8等都是stw-gc或者部分concurrent-gc。非引用计数的stw-gc方案可以分为3种,即标记-拷贝(简称marking-copy),标记-清理(简称marking-sweep),和标记-压缩(简称marking-compact)。

目前流行的高级语言虚拟机产品比如jvm,v8等的内存都是通过堆(heap)来进行统一管理,堆以指定大小的内存块(简称为一个page,一般为操作系统的内存页大小的整数倍)为基本单位进行组织。比如v8虚拟机的page大小为1mbyte。而且在每一个内存块(即page)的起始部分划分出一块位图区域(称为bitmap)用来标记所在的page中每一个对象是否是活跃对象。比如某个page中的某个对象对应在该page头部的bitmap位被置为1,则说明该对象是活跃对象,进行gc时候不应该进行回收。

当前用于垃圾回收的标记方法为单线程的标记方式,根据标记对象的不断增加,所占用的内存空间会不断增大,由此可见,目前的单线程标记方式浪费了大量的内存空间,降低了处理性能和效率。



技术实现要素:

本申请旨在至少在一定程度上解决相关技术中的技术问题之一。

为此,本申请的第一个目的在于提出一种用于垃圾回收的并行标记处理方法,该方法利用有限的内存实现多线程的并行标记处理,提高整个垃圾回收的性能。

本申请的第二个目的在于提出一种用于垃圾回收的并行标记处理方法。

本申请的第三个目的在于提出一种用于垃圾回收的并行标记处理装置。

本申请的第四个目的在于提出一种用于垃圾回收的并行标记处理装置。

为达上述目的,本申请第一方面实施例提出了一种用于垃圾回收的并行标记处理方法,包括:根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈;将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理;对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。

本申请实施例的用于垃圾回收的并行标记处理方法,通过根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n个标记线程占用的内存容量是预先设置的,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现多线程的并行标记处理,提高整个垃圾回收的性能。

为达上述目的,本申请第二方面实施例提出了一种用于垃圾回收的并行标记处理方法,包括:预设的n个标记线程中的每个标记线程至少包括:1个私有栈,所述方法应用在每个标记线程中,其中,应用在第一标记线程中的所述方法包括以下步骤:第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针;所述第一标记线程遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。

本申请实施例的用于垃圾回收的并行标记处理方法,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,实现了利用有限的内存进行并行标记处理,提高整个垃圾回收的性能。

为达上述目的,本申请第三方面实施例提出了一种用于垃圾回收的并行标记处理装置,包括:遍历模块,用于根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚 拟机堆中的第一对象,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈;第一标记模块,用于将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理;启动模块,用于对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。

本申请实施例的用于垃圾回收的并行标记处理装置,通过根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n个标记线程占用的内存容量是预先设置的,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现多线程的并行标记处理,提高整个垃圾回收的性能。

为达上述目的,本申请第四方面实施例提出了一种用于垃圾回收的并行标记处理装置,包括:预设的n个标记线程中的每个标记线程至少包括:1个私有栈,所述装置应用在每个标记线程中,其中,应用在第一标记线程中的所述装置包括:获取模块,用于根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针;第二标记模块,用于遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。

本申请实施例的用于垃圾回收的并行标记处理装置,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,实现了利用有限的内存进行并行标记处理,提高整个垃圾回收的性能。

附图说明

本发明上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:

图1是本申请一个实施例的用于垃圾回收的并行标记处理方法的流程图;

图2是本申请另一个实施例的用于垃圾回收的并行标记处理方法的流程图;

图3为用于垃圾回收的第一标记处理流程示意图;

图4为预先申请的n个标记线程的示意图;

图5是应用图4所示的标记线程并行标记处理的流程图一;

图6是应用图4所示的标记线程并行标记处理的流程图二;

图7是应用图4所示的标记线程并行标记处理的流程图三;

图8是应用图4所示的标记线程并行标记处理的流程图四;

图9是应用图4所示的标记线程并行标记处理的流程图五;

图10是应用图4所示的标记线程并行标记处理的流程图六;

图11是本申请一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图12是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图13是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图14是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图15是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图16是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图;

图17是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

具体实施方式

下面详细描述本申请的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,旨在用于解释本申请,而不能理解为对本申请的限制。

下面参考附图描述本申请实施例的用于垃圾回收的并行标记处理方法及装置。

图1是本申请一个实施例的用于垃圾回收的并行标记处理方法的流程图。

如图1所示,该用于垃圾回收的并行标记处理方法包括:

步骤101,根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈。

具体地,为了提高用于垃圾回收的标记处理效率,本发明各实施例提供的处理方法利用了多核cpu的并行处理能力,预先申请n个标记线程,其中,每个标记线程至少包括:1个私有栈,私有栈用于存储本线程负责标记的对象的指针。

需要说明的是,n为大于1的整数,根据实际应用的cpu的并行处理能力而定。例如:

如果cpu的并行处理能力为双核,可以申请2个容量限定的标记线程;或,

如果cpu的并行处理能力为四核,可以申请4个容量限定的标记线程;或,

如果cpu的并行处理能力为八核,可以申请8个容量限定的标记线程。

需要注意的是,以上仅为举例说明,可以根据实际应用需要进行设置和调整。

需要强调的是,随着标记对象的增加,现有的标记处理技术需要不断的增加标记线程的内存占用量,降低了标记处理的性能和效率。因此,本发明提供的并行标记处理方法,预先对n个标记线程占用的内存容量进行设置,也就是会所,n个标记线程占用的内存容量不会随着标记对象的溢出而增加,以便保证标记处理的性能和效率。

需要说明的是,可以根据应用需要采用多种方式对n个标记线程占用的内存容量进行设置,例如:

示例一,对每个标记线程的容量进行设置;

示例二,对n个标记线程占用的内存总容量进行设置,每个标记线程可以不限定,或者,比如限定最大的一个等。

为了提高标记效率,实现多线程并行标记的负载均衡,预先建立虚拟机堆中的内存块与n标记线程的对应关系。也就是说,预先为每个标记线程配置好对应负责标记的虚拟机堆中的内存块。

需要注意的是,可以根据实际应用需要建立虚拟机堆中内存块与n个标记线程的对应关系,例如包括:

示例一:为每个内存块指定对应的标记线程;或者,

示例二:为每个标记线程指定负责标记的内存块。

进而,从虚拟机系统中获取预先存储的虚拟机堆中所有的第一对象,根据上述设置的虚拟机堆中的内存块与n个标记线程的对应关系,遍历虚拟机堆中的第一对象。

步骤102,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理。

步骤103,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。

具体地,首先确定当前处理的第一对象所在的内存块,然后根据上述的对应关系获取与该第一对象所在的内存块对应的标记线程。将该第一对象的第一指针压入到与该第一对象所在的内存块对应的标记线程的私有栈中。

进而,根据该第一对象的第一指针的压入情况,对当前处理的第一对象进行第一标记处理。也就是说,如果将当前第一对象的第一指针成功压入到对应标记线程的私有栈中, 则确定该私有栈没有溢出,将当前处理的第一对象标记为压入状态;如果没有将当前第一对象的第一指针成功压入到对应标记线程的私有栈中,则确定该私有栈溢出,将当前处理的第一对象标记为溢出状态。

需要说明的是,对第一对象是否溢出的标记方式有很多,可以根据需要进行选择,例如:

示例一,可以通过列表的方式记录与每个标记线程的私有栈对应的第一对象的压入情况;或者,

示例二,可以通过第一对象所在内存块位图中的相应位置标记第一对象的压入情况。

需要说明的是,以上仅为举例说明,可以根据实际应用需要进行选择标记方式。

对虚拟机堆中的第一对象遍历完成后,各个标记线程的私有栈中都存放了本线程负责标记的内存块中第一对象的第一指针。如果标记线程的私有栈中溢出,说明私有栈的空间已满,无法继续存放本线程负责标记的内存块中第一对象的第一指针,则将这些第一对象标记为溢出状态。当标记线程的私有栈中有新的处理空间时,继续存放本线程负责标记的内存块中第一对象的第一指针。

进而,向n个标记线程发送线程启动指令,从而n个标记线程根据各自私有栈中第一指针的压入情况,同步进行用于垃圾回收的标记处理。

本申请实施例的用于垃圾回收的并行标记处理方法,通过根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n个标记线程占用的内存容量是预先设置的,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现多线程的并行标记处理,提高整个垃圾回收的性能。

为了更加清楚的说明上述实施例中虚拟机堆中所有内存块与n个标记线程的对应关系的建立过程,以及第一标记过程,通过图2所示实施例进行说明。

图2是本申请另一个实施例的用于垃圾回收的并行标记处理方法的流程图。

如图2所示,该用于垃圾回收的并行标记处理方法可以包括以下步骤:

步骤201,申请n个标记线程,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈。

具体地,根据实际应用需要和cpu的多核处理能力,设置标记线程的数量n,以及设置n个标记线程所占的内存容量。其中,每个标记线程包括一个私有栈,私有栈用于存储 本线程负责标记的对象的指针。

步骤202,遍历虚拟机堆的所有内存块,为每个内存块分配编号;

步骤203,根据内存块编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号。

具体地,为了向虚拟机堆的每个内存块分配负责标记内存块对象的标记线程,遍历虚拟机堆的内存块,为每个内存块分配编号。

进而,根据内存块编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号。

需要说明的是,根据内存块编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号的方式有很多,例如:可以通过获取标记线程总数n被内存块编号整除后的余数,确定与每个内存块编号对应的标记线程编号,公式表达如下所示:

id=id%n,其中,

n为标记线程总数;id为内存块编号;id为标记线程编号;“%”表示n被id整除后的取余处理。

例如:假设当前申请的标记线程总数n=4,编号分别为0-3,内存块为十个,编号分别为1-10,通过上述公式处理后获知:

内存块编号1对应的标记线程编号为0;

内存块编号2对应的标记线程编号为1;

内存块编号3对应的标记线程编号为2;

内存块编号4对应的标记线程编号为3;

内存块编号5对应的标记线程编号为0;

内存块编号6对应的标记线程编号为1;

内存块编号7对应的标记线程编号为2;

内存块编号8对应的标记线程编号为3;

内存块编号9对应的标记线程编号为1;

内存块编号10对应的标记线程编号为2。

步骤204,根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈;

步骤205,判断是否将当前第一对象的第一指针成功压入对应标记线程的私有栈中;

步骤206,如果将所述第一指针成功压入对应标记线程的私有栈,则将当前第一对象 所在内存块的位图中、与该第一对象对应的状态标记为压入状态;

步骤207,如果未能将所述第一指针成功压入对应标记线程的私有栈,则将当前第一对象所在内存块的位图中、与该第一对象对应的状态标记为溢出状态。

步骤208,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。

具体地,确定当前处理的第一对象所在的内存块,然后根据上述的对应关系获取与该第一对象所在的内存块对应的标记线程。将该第一对象的第一指针压入到与该第一对象所在的内存块对应的标记线程的私有栈中。

进而,根据该第一对象的第一指针的压入情况,对当前处理的第一对象进行第一标记处理。也就是说,如果将当前第一对象的第一指针成功压入到对应标记线程的私有栈中,则确定该私有栈没有溢出,将当前处理的第一对象标记为压入状态;如果没有将当前第一对象的第一指针成功压入到对应标记线程的私有栈中,则确定该私有栈溢出,将当前处理的第一对象标记为溢出状态。

对所述第一对象遍历完成后,各个标记线程的私有栈中都存放了本线程负责标记的内存块中第一对象的第一指针。如果标记线程的私有栈中溢出,说明私有栈的空间已满,无法继续存放本线程负责标记的内存块中第一对象的第一指针,则将这些第一对象标记为溢出状态。当标记线程的私有栈中有新的处理空间时,继续存放本线程负责标记的内存块中第一对象的第一指针。

进而,向n个标记线程发送线程启动指令,从而n个标记线程根据各自私有栈中第一指针的压入情况,同步进行用于垃圾回收的标记处理。

为了更加清楚的说明上述实施例中涉及的对第一对象进行第一标记处理的处理过程,通过图3所示实施例说明如下。

图3为用于垃圾回收的第一标记处理流程示意图。

参见图3,本实施例中采用在内存块位图中进行着色标记的方式对第一对象的压入情况进行第一标记处理,具体标记如下:

如果将当前处理的第一对象的第一指针成功压入对应标记线程的私有栈中,则将与该第一对象所在内存块位图中的对应位置进行标黑处理;

如果没有将当前处理的第一对象的第一指针成功压入对应标记线程的私有栈中,则将与该第一对象所在内存块位图中的对应位置进行标灰处理。

需要说明的是,以上根据第一对象的第一指针向对应标记线程的私有栈的不同压入情 况,在内存块位图中与第一对象的对应位置进行的着色处理仅仅是示例性说明,可以根据具体的应用需要进行调整。

基于上述标记方式,具体以处理虚拟堆中的根对象a(本示例中虚拟堆中的根对象相当于上述实施例中涉及的第一对象)为例说明如下:

步骤10:申请n个标记线程,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈。

步骤20:建立虚拟机堆中的内存块与n个标记线程的对应关系。

步骤30:遍历虚拟机堆中的根对象,如果遍历完毕,则退出,否则执行步骤40。

步骤40:将当前处理的根对象a的第一指针压入与a所在的内存块10对应的标记线程1的私有栈1中。

步骤50:判断是否将a的第一指针成功压入标记线程1的私有栈1中;

步骤60:如果将a的第一指针成功压入标记线程1的私有栈1中,则将内存块10的位图中、与a对应的位置标黑,即a为压入状态。

步骤70:如果没有将a的第一指针成功压入标记线程1的私有栈1中,则将内存块10的位图中、与a对应的位置标灰,即a为溢出状态。

本申请实施例的用于垃圾回收的并行标记处理方法,通过申请n个标记线程,遍历虚拟机堆的所有内存块,为每个内存块分配编号;根据内存块编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号,进而将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,提高整个垃圾回收的性能。

基于上述实施例,对所述第一对象遍历完成后,各个标记线程的私有栈中都存放了本线程负责标记的内存块中第一对象的第一指针。如果标记线程的私有栈中溢出,说明私有栈的空间已满,无法继续存放本线程负责标记的内存块中第一对象的第一指针,则将这些第一对象标记为溢出状态。当标记线程的私有栈中有新的处理空间时,继续存放本线程负责标记的内存块中第一对象的第一指针。

进而,向n个标记线程发送线程启动指令,从而n个标记线程根据各自私有栈中第一指针的压入情况,同步进行用于垃圾回收的标记处理。

需要说明的是,预先申请的n个标记线程的处理过程是同步并行的,为了更加清楚的 说明n个标记线程的标记处理过程,以第一标记线程的标记处理过程为例,通过下述实施例说明如下,其他(n-1)个标记线程的标记处理过程参见第一标记线程,不再一一赘述。

图4为预先申请的n个标记线程的示意图。

参见图4,预先申请的n个标记线程,以及n个标记线程所占用的内存容量。n个标记线程包括:thread-1、thread-2,…thread-n。其中,每个标记线程至少包括:1个私有栈(stack),经过上述处理,各个私有栈中存储有本线程负责标记的第一对象(rootobjects)的第一指针。

图5是应用图4所示的标记线程并行标记处理的流程图一。

参见图5,本实施例中以第一标记线程(thread-1)的标记处理过程为例,该用于垃圾回收的并行标记处理方法包括:

步骤301,第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针。

步骤302,所述第一标记线程遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。

具体地,第一标记线程接收到线程启动指令之后,根据该线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针。

进而,第一标记线程查询预存的对象关系表,获取当前处理的第一指针指示的第二对象,需要解释的是,第二对象为第一对象的引用对象。

第一标记线程遍历当前处理的第一指针指示的第二对象,根据预设的n个标记线程与虚拟机堆中内存块的对应关系,判断负责处理当前第二对象所在的内存块的标记线程是否为本线程,从而对第二对象进行第二标记处理。

本申请实施例,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,实现了利用有限的内存进行并行标记处理,提高整个垃圾回收的性能。

图6是应用图4所示的标记线程并行标记处理的流程图二。

继续参见图4,基于图5所示实施例,每个标记线程还包括:(n-1)个公用输出队列(queue-1、queue-2…queue-n-1),以及1个缓存队列(buf-queue)。其中,(n-1)个公用输出队列用于存储其他(n-1)个标记线程负责标记的对象的指针;当与其他(n-1)个标 记线程对应的公用输出队列溢出时,1个缓存队列用于缓存其他(n-1)个标记线程负责标记的对象的指针。

参见图6,继续以第一标记线程(thread-1)的标记处理过程为例,图5所示实施例中的步骤302具体包括:

步骤401,第一标记线程根据所述对应关系,判断是否负责对当前处理的第二对象所在的内存块p1进行标记处理;

具体地,第一标记线程根据预设的n个标记线程与虚拟机堆中内存块的对应关系,判断本线程是否负责对当前处理的第二对象所在的内存块p1进行标记处理。

如果第一标记线程获知负责对该内存块p1进行标记处理的标记线程为第一标记线程,即本线程负责对该内存块p1进行标记处理,进而执行步骤402-步骤406;

如果第一标记线程获知负责对该内存块p1进行标记处理的标记线程为标记线程m,标记线程m不是第一标记线程,即本线程不负责对该内存块p1进行标记处理,进而执行步骤407-步骤415。

步骤402,将当前处理的第二对象的第二指针压入到所述第一私有栈中。

具体地,针对步骤401中第一标记线程负责对所述内存块p1进行标记处理的判断分支,第一标记线程将负责处理对象的指针压入到本线程的私有栈中进行处理。即将当前处理的第二对象的第二指针压入到所述第一私有栈中进行第二标记处理。

步骤403,所述第一标记线程判断是否成功将所述第二指针压入到所述第一私有栈中。

具体地,第一标记线程判断是否成功将当前处理的第二对象的第二指针压入到本线程的第一私有栈中。

如果第一标记线程未能成功将当前处理的第二对象的第二指针压入到本线程的第一私有栈中,则执行步骤404和步骤405对第二对象进行溢出状态的标记处理;

如果第一标记线程成功将当前处理的第二对象的第二指针压入到本线程的第一私有栈中,则执行步骤406继续对下一个第二对象进行第二标记处理。

步骤404,将所述内存块p1的位图中、与该第二对象对应的状态标记为溢出状态。

步骤405,设置与所述内存块p1对应的溢出标志。

具体地,针对步骤403中第一标记线程未能成功将当前处理的第二对象的第二指针压入到本线程的第一私有栈中的判断分支,将第二对象设置为溢出状态。例如:将上述内存块p1的位图中、与该第二对象对应的状态标记为溢出状态。并且进一步地设置与该内存块p1对应的溢出标志。

步骤406,如果所述第一标记线程成功将所述第二指针压入到所述第一私有栈中,则 继续对所述第一指针对应的下一个第二对象进行处理。

具体地,针对步骤403中第一标记线程成功将所述第二指针压入到所述第一私有栈中的判断分支,继续对从第一私有栈中取出的第一指针对应的下一个第二对象进行处理。

步骤407,确定标记线程m负责对所述内存块p1进行标记处理;

步骤408,将所述第二指针压入到所述第一标记线程中与所述标记线程m对应的公用输出队列m中;

具体地,针对步骤401中第一标记线程不负责对所述内存块p1进行标记处理的判断分支,根据n个标记线程与虚拟机堆中内存块的对应关系,确定标记线程m负责对所述内存块p1进行标记处理。

进而,第一标记线程将当前处理的第二对象的第二指针压入到第一标记线程中与标记线程m对应的公用输出队列m中,以使标记线程m后续从第一标记线程中的公用输出队列m中获取待处理的第二对象的第二指针。

步骤409,所述第一标记线程判断是否成功将所述第二指针压入到所述公用输出队列m中;

第一标记线程判断是否成功将当前处理的第二对象的第二指针压入到公用输出队列m中。

如果第一标记线程成功将当前处理的第二对象的第二指针压入到第一标记线程中的公用输出队列m中,则执行步骤410,继续对当前从第一私有栈中中获取的第一指针对应的下一个第二对象进行处理。

如果第一标记线程未能成功将当前处理的第二对象的第二指针压入到第一标记线程中的公用输出队列m中,则执行步骤411,通过第一标记线程的第一缓存队列缓存该第二指针。

步骤410,继续对所述第一指针对应的下一个第二对象进行处理。

具体地,针对步骤409中第一标记线程成功将当前第二指针压入到第一标记线程中的公用输出队列m中的判断分支,继续对上述第一指针对应的下一个第二对象进行处理。

步骤411,将所述第二指针压入到所述第一标记线程中的第一缓存队列中;

具体地,针对步骤409中第一标记线程未能成功将当前第二指针压入到第一标记线程中的公用输出队列m中的判断分支,将该第二指针压入到第一标记线程中的第一缓存队列中。

步骤412,所述第一标记线程判断是否成功将所述第二指针压入到所述第一缓存队列中;

具体地,第一标记线程判断是否成功将该第二指针压入到第一标记线程的第一缓存队列中;

如果第一标记线程未能成功将所述第二指针压入到所述第一缓存队列中,则执行步骤413和步骤414,对当前处理的第二对象标记溢出状态;

如果第一标记线程成功将所述第二指针压入到所述第一缓存队列中,则执行步骤415,对下一个第二对象继续进行标记处理。

步骤413,将所述内存块p1的位图中、与当前处理的第二对象对应的状态标记为溢出状态。

步骤414,设置与所述内存块p1对应的溢出标志。

具体地,针对步骤412中第一标记线程未能成功将所述第二指针压入到所述第一缓存队列中的判断分支,将商户内存块p1的位图中、与当前处理的第二对象对应的状态标记为溢出状态,并进一步地设置与该内存块p1对应的溢出标志。

步骤415,继续对所述第一指针对应的下一个第二对象进行处理。

具体地,针对步骤412中第一标记线程成功将所述第二指针压入到所述第一缓存队列中的判断分支,继续对当前第一指针对应的下一个第二对象进行处理。

基于图6所示实施例,进一步地,在步骤401之前,还包括:

查询当前处理的第二对象所在内存块p1的位图中与该第二对象对应的状态标记。如果与该第二对象对应的状态标记为未标记状态,则将与该第二对象对应的状态修改为压入状态。

需要说明的是,对第二对象是否溢出的标记方式有很多,可以根据需要进行选择,例如:

示例一,可以通过列表的方式记录与每个第二对象的压入情况;或者,

示例二,可以通过第二对象所在内存块位图中的相应位置标记第二对象的压入情况。

需要说明的是,以上仅为举例说明,可以根据实际应用需要进行选择标记方式。

本申请实施例,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图7是应用图4所示的标记线程并行标记处理的流程图三。

继续参见图4,每个标记线程包括:1个私有栈(stack)、(n-1)个公用输出队列(queue-1、queue-2…queue-n-1),以及1个缓存队列(buf-queue)。其中,1个私有栈(stack)用于存储本线程负责标记的对象的指针;(n-1)个公用输出队列用于存储其他(n-1)个标记线程负责标记的对象的指针;当与其他(n-1)个标记线程对应的公用输出队列溢出时,1个缓存队列用于缓存其他(n-1)个标记线程负责标记的对象的指针。

参见图7,基于图5所示实施例,所述方法还包括:

步骤501,第一标记线程接到线程启动指令后,判断本线程的第一私有栈是否为空;

具体地,第一标记线程判断本线程的第一私有栈是否为空;

如果第一标记线程的第一私有栈不为空,则按照图5中所示实施例中的步骤302从第一私有栈中取出预先压入的第一对象的第一指针,并按照图5或图6所示的实施过程进行处理,此处不再赘述。

如果第一标记线程的第一私有栈为空,则执行步骤502继续判断第一标记线程中的第一缓存队列是否为空。

步骤502,所述第一标记线程判断本线程的第一缓存队列是否为空;

具体地,第一标记线程判断本线程的第一缓存队列是否为空;

如果第一标记线程中的第一缓存队列不为空,执行步骤503,从而对第一标记线程不负责处理的第三对象向本线程中与该第三对象对应的公用输出队列进行分配处理;

如果第一标记线程中的第一缓存队列为空,则通过图8所示实施例描述如何进一步地对其他(n-1)个标记线程中与第一标记线程对应的公用输出队列中的第四对象进行标记处理,后续实施例详细说明。

步骤503,所述第一标记线程从所述第一缓存队列中取出预先压入的第三对象的第三指针,其中,所述第一标记线程不负责对当前处理的第三对象所在的内存块p2进行标记处理;

步骤504,所述第一标记线程根据所述对应关系,确定标记线程w负责对当前处理的第三对象所在的内存块p2进行标记处理;

步骤505,所述第一标记线程将所述第三指针压入到所述第一标记线程中与所述标记线程w对应的公用输出队列w中;

具体地,第一标记线程从本线程的第一缓存队列中取出预先压入的第三对象的第三指针,由于第一缓存队列中存放的对象是需要放入第一标记线程中的公用输出队列中,以供对应的其他标记线程进行处理的。当第一标记线程中的公用输出队列中出现溢出时,将溢出的第三对象放入第一标记线程中的第一缓存队列中缓存。

由此可见,第一标记线程不负责对当前处理的第三对象所在的内存块p2进行标记处理。第一标记线程根据虚拟机堆的内存块与标记线程的对应关系,确定标记线程w负责对当前处理的第三对象所在的内存块p2进行标记处理。

进而,第一标记线程将该第三指针压入到第一标记线程中与标记线程w对应的公用输出队列w中,以供标记线程w从第一标记线程的公用输出队列w中获取该第三指针进行标记处理。

步骤506,所述第一标记线程判断是否成功将当前处理的第三指针压入到所述公用输出队列w中;

步骤507,继续对所述第一缓存队列中的下一个第三对象向对应的公用输出队列进行压入处理。

步骤508,将所述第三指针重新压入所述第一缓存队列中。

具体地,第一标记线程判断是否成功将当前处理的第三指针压入到本线程的公用输出队列w中。

如果第一标记线程成功将该第三指针压入到本线程的公用输出队列w中,则执行步骤507,继续对所第一缓存队列中的下一个第三对象向对应的公用输出队列进行压入处理。

如果第一标记线程未能成功将该第三指针压入到本线程的公用输出队列w中,则将该第三指针重新压入本线程的第一缓存队列中。此时,不存在溢出的问题,因为该第三指针就是从本线程的第一缓存队列中取出来的。

基于上述实施例,本申请在第一标记线程的第一私有栈为空时,且第一缓存队列不为空,从第一缓存队列中取出预先压入的第三对象的第三指针,向本线程中与对应标记线程的公用输出队列中进行压入处理,以供与第三对象对应的标记线程对其进行标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的进行协同并行的标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图8是应用图4所示的标记线程并行标记处理的流程图四。

参见图8,基于图7所示实施例,本实施例是基于图7中的步骤502,针对如果第一标记线程中的第一缓存队列为空的判断分支,通过图8所示实施例描述如何进一步地对其他(n-1)个标记线程中与第一标记线程对应的公用输出队列中的第四对象进行标记处理,具体包括:

步骤601,第一标记线程判断其他(n-1)个标记线程中与所述第一标记线程对应的公用输出队列是否为空;

具体地,第一标记线程判断其他(n-1)个标记线程中与所述第一标记线程对应的公用输出队列是否为空;

如果其他(n-1)个标记线程中与第一标记线程对应的公用输出队列不为空,则执行步骤602,从而第一标记线程从其他标记线程中获取本线程负责处理的第四对象,向本线程的第一私有栈进行压入处理。

如果其他(n-1)个标记线程中与第一标记线程对应的公用输出队列为空,则通过图9所示实施例描述如何进一步地对第一标记线程负责标记的、且具有溢出状态的第五对象进行标记处理,后续实施例详细说明。

步骤602,第一标记线程从当前处理的公用输出队列中取出预先压入的第四对象的第四指针,其中,所述第四对象为所述标记线程t预先压入的、由所述第一标记线程负责对所述第四对象所在的内存块p3进行标记处理;

步骤603,所述第一标记线程将所述第四指针压入到所述第一私有栈中;

具体地,针对步骤601中如果其他(n-1)个标记线程中与第一标记线程对应的公用输出队列不为空的判断分支,说明其他的标记线程中还具有需要由第一标记线程标记处理的第四对象。

进而,第一标记线程从当前处理的公用输出队列中取出预先压入的第四对象的第四指针,其中,该第四对象为标记线程t预先压入的、并且由第一标记线程负责对该第四对象所在的内存块p3进行标记处理。从而第一标记线程将该第四指针压入到所述第一私有栈中。

步骤604,所述第一标记线程判断是否成功将所述第四指针压入到所述第一私有栈中;

步骤605,将所述内存块p3的位图中、与该第四对象对应的状态标记为溢出状态。

步骤606,设置与所述内存块p3对应的溢出标志。

步骤607,继续对下一个第四对象向所述第一私有栈中进行压入处理。

具体地,第一标记线程判断是否成功将该第四指针压入到本线程的第一私有栈中。

如果第一标记线程未能成功将该第四指针压入到本线程的第一私有栈中,则执行步骤605和步骤606,将该第四对象所在的内存块p3的位图中、与该第四对象对应的状态标记为溢出状态,并且设置与所述内存块p3对应的溢出标志。

如果第一标记线程成功将该第四指针压入到本线程的第一私有栈中,则则执行步骤607,继续对下一个第四对象向本线程的第一私有栈中进行压入处理。

基于上述实施例,本申请的第一标记线程在第一私有栈和第一缓存队列为空,且其他标记线程中与第一标记线程对应的公用输出队列不为空时,取出预先压入的第四对象的第 四指针,向本线程中的第一私有栈压入处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的进行协同并行的标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图9是应用图4所示的标记线程并行标记处理的流程图五。

参见图9,基于图8所示实施例,本实施例是基于图9中的步骤601,针对如果其他(n-1)个标记线程中与第一标记线程对应的公用输出队列为空的判断分支,则通过图9所示实施例描述如何进一步地对第一标记线程负责标记的、且具有溢出状态的第五对象进行标记处理,具体包括:

步骤701,第一标记线程判断本线程负责标记的内存块中是否有溢出状态的第五对象;

步骤702,如果所述第一标记线程负责标记的内存块中不具有溢出状态的第五对象,则标记结束,退出线程。

步骤703,如果所述第一标记线程负责标记的内存块中具有溢出状态的第五对象,所述第一标记线程将当前处理的内存块p4中标记溢出状态的第五对象修改为压入状态,将当前第五对象的第五指针压入到所述第一私有栈中;

具体地,第一标记线程判断本线程负责标记的内存块中是否有溢出状态的第五对象。

如果第一标记线程负责标记的内存块中不具有溢出状态的第五对象,则说明本线程负责标记的对象遍历完成,标记结束,执行步骤702退出线程。

如果第一标记线程负责标记的内存块中具有溢出状态的第五对象,则说明本线程负责标记的对象还没有遍历完成。进而,第一标记线程执行步骤703,将当前处理的内存块p4中标记溢出状态的第五对象修改为压入状态,将当前第五对象的第五指针压入到所述第一私有栈中。

步骤704,所述第一标记线程判断是否成功将所述第五指针压入到所述第一私有栈中;

步骤705,如果所述第一标记线程未能成功将所述第五指针压入到所述第一私有栈中,则将所述内存块p4的位图中、与该第五对象对应的状态标记为溢出状态。

步骤706,设置与所述内存块p5对应的溢出标志。

步骤707,如果所述第一标记线程成功将所述第五指针压入到所述第一私有栈中,则继续对下一个第五对象进行处理。

具体地,第一标记线程判断是否成功将当前的第五指针压入到本线程的第一私有栈中。

如果第一标记线程未能成功将该第五指针压入到本线程的第一私有栈中,则说明第一私有栈空间不足有溢出,则执行步骤705和步骤706,将该第五对象所在的内存块p4的位图中、与该第五对象对应的状态标记为溢出状态,并且进一步地设置与所述内存块p5对应 的溢出标志。

如果第一标记线程成功将该第五指针压入到本线程的第一私有栈中,则执行步骤707,继续对下一个第五对象进行处理。

基于上述实施例,本申请的第一标记线程在第一私有栈、第一缓存队列、以及其他标记线程中与第一标记线程对应的公用输出队列都为空时,根据本线程负责标记的具有溢出状态的第五对象进行压入处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行的标记处理,利用有限的内存实现高效的并行标记,提高整个垃圾回收的性能。

为了更加清楚的说明图4-图9所示实施例中涉及的对第二对象至第五对象进行处理的处理过程,通过图10所示实施例说明如下。

图10是应用图4所示的标记线程并行标记处理的流程图六。

参见图10,本实施例中采用在内存块位图中进行着色标记的方式对第二对象至第五对象的压入情况进行标记处理,具体标记如下:

如果将当前处理的对象的指针成功压入对应的目标空间中,则将与当前对象所在内存块位图中的对应位置进行标黑处理;

如果没有将当前处理的对象的指针成功压入对应的目标空间中,则将与当前对象所在内存块位图中的对应位置进行标灰处理;

如果当前处理对象所在内存块位图中的对应位置为标白状态,说明该对象为未处理状态。

需要说明的是,以上根据处理对象的指针向对应目标空间的不同压入情况,在内存块位图中与当前处理对象的对应位置进行的着色处理仅仅是示例性说明,可以根据具体的应用需要进行调整。

基于上述标记方式,具体以对象a等同于上述实施例中涉及的第一对象,对象a1等同于上述实施例中涉及的第二对象,对象b等同于上述实施例中涉及的第三对象,对象d等同于上述实施例中涉及的第四对象,对象c等同于上述实施例中涉及的第五对象,举例说明如下:

如图10所示,该并行标记处理方法包括:

步骤1:线程启动。

步骤2:如果私有stack已经空了,则跳转到步骤3。否则弹出一个对象比如a,跳转到步骤4。

步骤3:如果buf-queue为空,跳转到步骤7,否则遍历buf-queue,弹出对象比如b,跳转到步骤5。如果已经遍历完成,则跳转到步骤7。

步骤4:依次遍历对象a所引用的所有对象,遍历完成则跳转到步骤2。否则,比如遍历到对象a1,并跳转到步骤9。

步骤5:尝试把步骤3中弹出来的对象b压入本线中t(b)号queue中,压入成功则跳转到步骤3,反之标记对象b所在的page(内存块)溢出,然后跳转到步骤6。

步骤6:对象b重新压回到buf-queue中,这时候不会失败,因为对象b是从buf-queue中弹出来的。

步骤7:遍历另外n-1个线程中的本线程对应的queue,取出标记对象。只要有一个queue非空,则pop出(弹出)标记对象,比如对象d,然后跳转到步骤16。如果所有n-1个线程中和本线程对应的queue都为空,则跳转到步骤8。

步骤8:遍历本线程负责的page时如发现有溢出,则遍历有溢出的page的bitmap(位图),找到灰色的对象比如c,如果找到则跳转到步骤14。遍历完毕,清理page的溢出标志,然后跳转到步骤15。

步骤9:判断步骤4中遍历到的对象a1所在的page的对应的bitmap是否为白色,如果已经是黑色则跳转到步骤4。如果是白色,则跳转到步骤10。

步骤10:标记对象a1所在的page的对应的bitmap值为黑色。如果t(a1)为本线程,则跳转到步骤17。否则跳转到步骤11。

步骤11:尝试把对象a1压入本线程的t(a1)号queue中,如果压入失败,则设置a1所在的page的溢出。并跳转到步骤12,如果成功,则跳转到步骤4。

步骤12:尝试把对象a1压入buf-queue,如果成功则跳转到步骤4。反之跳转到步骤13。

步骤13:设置对象a1所在的page对应的bitmap的值为灰色,并设置page的溢出标志。

步骤14:把步骤8遍历到的灰色对象c标记对应的bitmap为黑色并压入私有栈stack中,如果成功则跳转到步骤8。如果失败,则设置c所在的page的溢出标志,并跳转到步骤19。

步骤15:如果标记结束,则线程退出,否则跳转到步骤2,继续并行标记。

步骤16:标记对象d对应的bitmap为黑色,尝试把对象d压入本线程的stack中,如压入成功,跳转到步骤7。溢出跳转到步骤19。

步骤17:尝试把对象a1压入本线程的私有stack中,如果压入成功即没有溢出,则跳转到步骤4,否则跳转到步骤18。

步骤18:标记对象a1对应的bitmap为灰色,并设置a1所在的page的溢出标志。 然后跳转到步骤4。

步骤19:标记对象(d或者c,即可能来自步骤14或者16)对应的bitmap为灰色,并设置标记对象所在的page的溢出标志。然后跳转到步骤2。

具体地,结合本示例中的19个步骤和附图,具体通过下述的处理步骤示意图6至图9的处理过程,其详细的描述过程参见图6至图9所示实施例,此处不再赘述。

针对图6所示实施例的处理过程如下示意的步骤流程(1),其具体实施过程参见上述实施例,此处不再赘述。

步骤流程(1):

针对图7所示实施例的处理过程如下示意的步骤流程(2),其具体实施过程参见上述实施例,此处不再赘述。

步骤流程(2):

针对图8所示实施例的处理过程如下示意的步骤流程(3),其具体实施过程参见上述实施例,此处不再赘述。

步骤流程(3):

针对图9所示实施例的处理过程如下示意的步骤流程(4),其具体实施过程参见上述 实施例,此处不再赘述。

步骤流程(4):

为了实现上述实施例,本申请还提出一种用于垃圾回收的并行标记处理装置。

图11是本申请一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图11,该用于垃圾回收的并行标记处理装置包括:

遍历模块11,用于根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n为大于1的整数,n个标记线程占用的内存容量是预先设置的,每个标记线程至少包括:1个私有栈;

第一标记模块12,用于将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理;

启动模块13,用于对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,通过根据虚拟机堆中的内存块与n个标记线程的对应关系,遍历所述虚拟机堆中的第一对象,其中,n个标记线程占用的内存容量是预先设置的,将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现多线程的并行标记处理,提高整个垃圾回收的性能。

图12是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图12,基于图11,该用于垃圾回收的并行标记处理装置还包括:

申请模块14,用于申请所述n个标记线程;

建立模块15,用于遍历所述虚拟机堆中的内存块,建立内存块与n个标记线程的对应关系。

具体地,所述建立模块15用于:

为每个内存块指定对应的标记线程;或者,

为每个标记线程指定负责标记的内存块。

其中,在一个具体的示例中,所述建立模块15包括:

分配单元151,用于遍历虚拟机堆中的内存块,为每个内存块分配编号;

确定单元152,用于根据内存块的编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号。

具体地,所述确定单元152用于:

获取标记线程总数n被内存块编号整除后的余数,确定与每个内存块编号对应的标记线程编号。

具体地,所述第一标记模块12用于:

如果将所述第一指针成功压入与当前第一对象所在的内存块对应的标记线程的私有栈,则将当前第一对象所在内存块的位图中、与该第一对象对应的状态标记为压入状态;

如果未能将所述第一指针成功压入与当前第一对象所在的内存块对应的标记线程的私有栈,则将当前第一对象所在内存块的位图中、与该第一对象对应的状态标记为溢出状态。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,通过申请n个标记线程,遍历虚拟机堆的所有内存块,为每个内存块分配编号;根据内存块编号和标记线程总数n,确定与每个内存块编号对应的标记线程编号,进而将当前处理的第一对象的第一指针压入与该第一对象所在的内存块对应的标记线程的私有栈,根据所述第一指针的压入情况对所述第一对象进行第一标记处理,对所述第一对象遍历完成后,向所述n个标记线程发送线程启动指令,以使所述n个标记线程根据各自私有栈中所述第一指针的压入情况,同步进行用于垃圾回收的标记处理。由此,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,提高整个垃圾回收的性能。

图13是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图13,本实施例中预先申请的n个标记线程,以及n个标记线程所占用的内存容量。n个标记线程包括:thread-1、thread-2,…thread-n。其中,每个标记线程至少包 括:1个私有栈(stack),经过上述处理,各个私有栈中存储有本线程负责标记的第一对象(rootobjects)的第一指针。本实施例中用于垃圾回收的并行标记处理装置包括:

获取模块21,用于根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针;

第二标记模块22,用于遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,实现了利用有限的内存进行并行标记处理,提高整个垃圾回收的性能。

图14是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图14,基于图13所示实施例,所述第二标记模块22包括:

第一判断单元221,用于根据所述对应关系,判断是否负责对当前处理的第二对象所在的内存块p1进行标记处理;

第一处理单元222,用于如果所述第一标记线程负责对所述内存块p1进行标记处理,则将当前处理的第二对象的第二指针压入到所述第一私有栈中;

第二判断单元223,用于判断是否成功将所述第二指针压入到所述第一私有栈中;

第二处理单元224,用于如果所述第一标记线程未能成功将所述第二指针压入到所述第一私有栈中,则将所述内存块p1的位图中、与该第二对象对应的状态标记为溢出状态。

进一步地,所述第二处理单元224还用于:

设置与所述内存块p1对应的溢出标志。

进一步地,在另一个实施例中,

所述第二处理单元224还用于:如果所述第一标记线程成功将所述第二指针压入到所述第一私有栈中,则继续对所述第一指针对应的下一个第二对象进行处理。

进一步地,在另一个实施例中,所述第二标记模块22还包括:

所述第一处理单元222,还用于如果所述第一标记线程不负责对所述内存块p1进行标 记处理,确定标记线程m负责对所述内存块p1进行标记处理,将所述第二指针压入到所述第一标记线程中与所述标记线程m对应的公用输出队列m中;

第三判断单元225,用于判断是否成功将所述第二指针压入到所述公用输出队列m中;

第三处理单元226,用于如果所述第一标记线程成功将所述第二指针压入到所述公用输出队列m中,则继续对所述第一指针对应的下一个第二对象进行处理。

进一步地,在另一个实施例中,所述第二标记模块22还包括:

所述第三处理单元226,还用于如果所述第一标记线程未能成功将所述第二指针压入到所述公用输出队列m中,则把所述第二指针压入到所述第一标记线程中的第一缓存队列中;

第四判断单元227,用于判断是否成功将所述第二指针压入到所述第一缓存队列中;

第四处理单元228,用于如果所述第一标记线程未能成功将所述第二指针压入到所述第一缓存队列中,则将所述内存块p1的位图中、与当前处理的第二对象对应的状态标记为溢出状态。

进一步地,在另一个实施例中,

所述第四处理单元228还用于:

设置与所述内存块p1对应的溢出标志。

进一步地,在另一个实施例中,

所述第四处理单元228,还用于如果所述第一标记线程成功将所述第二指针压入到所述第一缓存队列中,则继续对所述第一指针对应的下一个第二对象进行处理。

进一步地,在另一个实施例中,

所述第二处理单元224,还用于查询所述内存块p1的位图中与该第二对象对应的状态标记;如果与该第二对象对应的状态标记为未标记状态,则将与该第二对象对应的状态修改为压入状态。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,通过第一标记线程根据线程启动指令,从第一私有栈中取出预先压入的第一对象的第一指针,遍历所述第一指针指示的所述第一对象引用的第二对象,并根据预设的n个标记线程与虚拟机堆中内存块的对应关系对所述第二对象进行第二标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图15是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图15,基于图13所示实施例,本实施例中预设的n个标记线程中每个标记线程还包括:1个缓存队列,以及与其他(n-1)个标记线程对应的(n-1)个公用输出队列;所述第二标记模块22还包括:

第五判断单元229,用于判断所述第一私有栈是否为空;

第六判断单元210,用于如果所述第一私有栈为空,判断第一标记线程的第一缓存队列是否为空;

第五处理单元211,用于如果所述第一缓存队列不为空,所述第一标记线程从所述第一缓存队列中取出预先压入的第三对象的第三指针,其中,所述第一标记线程不负责对当前处理的第三对象所在的内存块p2进行标记处理;根据所述对应关系,确定标记线程w负责对当前处理的第三对象所在的内存块p2进行标记处理;将所述第三指针压入到所述第一标记线程中与所述标记线程w对应的公用输出队列w中;

第七判断单元212,用于判断是否成功将当前处理的第三指针压入到所述公用输出队列w中;

第六处理单元213,用于如果所述第一标记线程成功将所述第三指针压入到所述公用输出队列w中,则继续对所述第一缓存队列中的下一个第三对象向对应的公用输出队列进行压入处理。

进一步地,在另一个实施例中,

所述第六处理单元213,还用于如果所述第一标记线程未能成功将所述第三指针压入到所述公用输出队列w中,则将所述第三指针重新压入所述第一缓存队列中。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,在第一标记线程的第一私有栈为空时,且第一缓存队列不为空,从第一缓存队列中取出预先压入的第三对象的第三指针,向本线程中与对应标记线程的公用输出队列中进行压入处理,以供与第三对象对应的标记线程对其进行标记处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的进行协同并行的标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图16是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图16,基于图15所示实施例,所述第二标记模块22还包括:

第八判断单元214,用于如果所述第一缓存队列为空,判断其他(n-1)个标记线程中 与所述第一标记线程对应的公用输出队列是否为空;

第七处理单元215,用于如果当前处理的标记线程t中与所述第一标记线程对应的公用输出队列不为空,所述第一标记线程从当前处理的公用输出队列中取出预先压入的第四对象的第四指针,其中,所述第四对象为所述标记线程t预先压入的、由所述第一标记线程负责对所述第四对象所在的内存块p3进行标记处理;将所述第四指针压入到所述第一私有栈中;

第九判断单元216,用于判断是否成功将所述第四指针压入到所述第一私有栈中;

第八处理单元217,用于如果所述第一标记线程未能成功将所述第四指针压入到所述第一私有栈中,则将所述内存块p3的位图中、与该第四对象对应的状态标记为溢出状态。

进一步地,在另一个实施例中,

所述第八处理单元217,还用于设置与所述内存块p3对应的溢出标志。

进一步地,在另一个实施例中,

所述第八处理单元217,还用于如果所述第一标记线程成功将所述第四指针压入到所述第一私有栈中,则继续对下一个第四对象向所述第一私有栈中进行压入处理。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,第一标记线程在第一私有栈和第一缓存队列为空,且其他标记线程中与第一标记线程对应的公用输出队列不为空时,取出预先压入的第四对象的第四指针,向本线程中的第一私有栈压入处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的进行协同并行的标记处理,利用有限的内存实现高效的并行标记,同时实现标记线程负载均衡,从而减少cpu缓存一致性冲突,提高整个垃圾回收的性能。

图17是本申请另一个实施例的用于垃圾回收的并行标记处理装置的结构示意图。

参见图17,基于图16所示实施例,所述第二标记模块22还包括:

第十判断单元218,用于如果其他(n-1)个标记线程中与所述第一标记线程对应的公用输出队列都为空,所述第一标记线程判断本线程负责标记的内存块中是否有溢出状态的第五对象;

第九处理单元219,用于如果所述第一标记线程负责标记的内存块中具有溢出状态的第五对象,所述第一标记线程将当前处理的内存块p4中标记溢出状态的第五对象修改为压入状态,将当前第五对象的第五指针压入到所述第一私有栈中;

第十一判断单元220,用于所述第一标记线程判断是否成功将所述第五指针压入到所 述第一私有栈中;

第十处理单元221,用于如果所述第一标记线程未能成功将所述第五指针压入到所述第一私有栈中,则将所述内存块p4的位图中、与该第五对象对应的状态标记为溢出状态。

进一步地,在另一个实施例中,

所述第十处理单元221,还用于设置与所述内存块p5对应的溢出标志。

进一步地,在另一个实施例中,

所述第十处理单元221,还用于如果所述第一标记线程成功将所述第五指针压入到所述第一私有栈中,则继续对下一个第五对象进行处理。

进一步地,在另一个实施例中,

所述第九处理单元219,还用于如果所述第一标记线程负责标记的内存块中不具有溢出状态的第五对象,则标记结束,退出线程。

需要说明的是,前述对用于垃圾回收的并行标记处理方法实施例的解释说明也适用于该实施例的用于垃圾回收的并行标记处理装置,此处不再赘述。

本实施例提供的用于垃圾回收的并行标记处理装置,第一标记线程在第一私有栈、第一缓存队列、以及其他标记线程中与第一标记线程对应的公用输出队列都为空时,根据本线程负责标记的具有溢出状态的第五对象进行压入处理。由此,参照第一标记线程的标记处理过程,通过n个标记线程的并行的标记处理,利用有限的内存实现高效的并行标记,提高整个垃圾回收的性能。

在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本申请的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。

此外,术语“第一”、“第二”仅用于描述目的,而不能理解为指示或暗示相对重要性或者隐含指明所指示的技术特征的数量。由此,限定有“第一”、“第二”的特征可以明示或者隐含地包括至少一个该特征。在本申请的描述中,“多个”的含义是至少两个,例如两个,三个等,除非另有明确具体的限定。

流程图中或在此以其他方式描述的任何过程或方法描述可以被理解为,表示包括一个或更多个用于实现特定逻辑功能或过程的步骤的可执行指令的代码的模块、片段或部分, 并且本申请的优选实施方式的范围包括另外的实现,其中可以不按所示出或讨论的顺序,包括根据所涉及的功能按基本同时的方式或按相反的顺序,来执行功能,这应被本申请的实施例所属技术领域的技术人员所理解。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1