CN116685957A - 跟踪引用的垃圾收集状态 - Google Patents

跟踪引用的垃圾收集状态 Download PDF

Info

Publication number
CN116685957A
CN116685957A CN202180086504.8A CN202180086504A CN116685957A CN 116685957 A CN116685957 A CN 116685957A CN 202180086504 A CN202180086504 A CN 202180086504A CN 116685957 A CN116685957 A CN 116685957A
Authority
CN
China
Prior art keywords
garbage collection
state
media
references
heap
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN202180086504.8A
Other languages
English (en)
Inventor
E·厄斯特伦德
P·利登
S·M·R·卡尔松
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Oracle International Corp
Original Assignee
Oracle International Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Oracle International Corp filed Critical Oracle International Corp
Publication of CN116685957A publication Critical patent/CN116685957A/zh
Pending legal-status Critical Current

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F12/00Accessing, addressing or allocating within memory systems or architectures
    • G06F12/02Addressing or allocation; Relocation
    • G06F12/0223User address space allocation, e.g. contiguous or non contiguous base addressing
    • G06F12/023Free address space management
    • G06F12/0253Garbage collection, i.e. reclamation of unreferenced memory
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F12/00Accessing, addressing or allocating within memory systems or architectures
    • G06F12/02Addressing or allocation; Relocation
    • G06F12/0223User address space allocation, e.g. contiguous or non contiguous base addressing
    • G06F12/023Free address space management
    • G06F12/0253Garbage collection, i.e. reclamation of unreferenced memory
    • G06F12/0269Incremental or concurrent garbage collection, e.g. in real-time systems
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F2212/00Indexing scheme relating to accessing, addressing or allocation within memory systems or architectures
    • G06F2212/10Providing a specific technical effect
    • G06F2212/1016Performance improvement
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F2212/00Indexing scheme relating to accessing, addressing or allocation within memory systems or architectures
    • G06F2212/70Details relating to dynamic memory management
    • G06F2212/702Conservative garbage collection
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F2212/00Indexing scheme relating to accessing, addressing or allocation within memory systems or architectures
    • G06F2212/72Details relating to flash memory management
    • G06F2212/7205Cleaning, compaction, garbage collection, erase control

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

垃圾收集(GC)状态被存储在存储在堆存储器上的引用内,以跟踪相对于引用的GC操作的进度。GC状态可以被存储在引用的不可寻址部分中。基于特定引用的GC状态,为该引用选择并执行一组GC操作。然而,存储在调用堆栈上的引用不包括GC状态的任何指示。因此,将引用从堆加载到调用堆栈涉及移除GC状态的指示。将引用写入到堆涉及添加GC状态的指示。嵌入在已编译方法内的引用也不指示任何GC状态。已编译方法的元数据指示GC状态,其隐含到嵌入的引用。基于已编译方法的GC状态,为每个嵌入的引用选择和执行GC操作。

Description

跟踪引用的垃圾收集状态
技术领域
本公开涉及垃圾收集。具体地,本公开涉及跟踪引用(reference)的垃圾收集状态。
背景技术
编译器将根据旨在方便程序员的规范所编写的源代码转换成机器代码(也称为“本机(native)代码”或“目标代码”)。机器代码可直接由物理机器环境执行。附加地或替代地,编译器将源代码转换成中间表示(也称为“虚拟机代码/指令”),诸如字节码,其可由能够在各种物理机器环境之上运行的虚拟机执行。虚拟机指令可由虚拟机以比源代码更直接和更高效的方式执行。将源代码转换成虚拟机指令包括根据规范将源代码功能映射到虚拟机功能,这利用了虚拟机的底层资源(诸如数据结构)。通常,程序员经由源代码以简单术语呈现的功能被转换成更复杂的步骤,这些步骤更直接地映射到虚拟机所在的底层硬件所支持的指令集。
虚拟机通过执行源代码的中间表示(诸如字节码)来执行应用和/或程序。虚拟机的解释器将中间表示转换成机器代码。在执行应用时,会为程序所创建的对象分配一定的存储器(也称为“堆存储器(heap memory)”)。垃圾收集系统可以被用于自动地回收(reclaim)应用不再使用的对象所占用的存储器位置。垃圾收集系统使程序员不必明确指定要释放的对象。然而,应用在等待垃圾收集操作完成时经常需要暂停。减少这些暂停时间的一种方法是使用至少在垃圾收集周期的一些阶段支持并发垃圾收集操作的垃圾收集器。应用只需要在非并发(non-concurrent)垃圾收集操作期间暂停,但可以在并发垃圾收集操作期间并发地运行(包括在必要时继续分配新对象)。
在本部分中描述的方法是可以实行的方法,但不一定是先前已经构想或实行的方法。因此,除非另外指出,否则不应当假设在本部分中描述的任何方法仅仅因为其包括在本部分中就被认为是现有技术。
附图说明
在附图的各个图中,实施例是作为示例而不是作为限制进行图示的。应当注意的是,在本公开中对“一个”实施例的引用不一定是指相同的实施例,并且它们意味着至少一个。在附图中:
图1图示了在其中可以实践本文描述的技术的示例计算体系架构。
图2是图示适合于实现本文描述的方法和特征的计算机系统的一个实施例的框图。
图3图示了根据实施例的以框图形式的示例虚拟机存储器布局。
图4图示了根据实施例的以框图形式的示例帧。
图5图示了根据实施例的虚拟机的执行引擎和堆存储器。
图6图示了根据实施例的堆引用(heap reference)和可解除引用的引用(dereferencable reference)。
图7图示了根据实施例的垃圾收集周期。
图8A-图8D图示了根据实施例的垃圾收集处理。
图9图示了根据实施例的多个垃圾收集周期和对应的良好垃圾收集状态(或“良好颜色”)。
图10图示了根据实施例的引用加载屏障(reference load barrier)。
图11图示了根据实施例的引用写入屏障(reference write barrier)。
图12图示了根据实施例的已编译方法加载屏障(compiled method loadbarrier)。
图13图示了根据实施例的用于由垃圾收集线程标记(mark)堆引用的一组操作。
图14图示了根据实施例的用于由应用线程加载堆引用的一组操作。
图15图示了根据实施例的用于将堆引用从当前垃圾收集状态带入良好垃圾收集状态的一组路径。
图16图示了根据实施例的用于由应用线程写入堆引用的一组操作。
图17图示了根据实施例的用于由应用线程加载已编译方法(compiled method)的一组操作。
图18图示了根据实施例的用于将嵌入的引用(embedded reference)从当前垃圾收集状态带入良好垃圾收集状态的一组路径。
图19图示了根据一个或多个实施例的系统。
具体实施方式
在以下描述中,为了解释的目的,阐述了许多具体细节以便提供透彻的理解。可以在没有这些具体细节的情况下实践一个或多个实施例。在一个实施例中描述的特征可以与在不同实施例中描述的特征组合。在一些示例中,参考框图形式来描述众所周知的结构和设备,以便避免不必要地模糊本发明。
1.总体概述
2.体系架构概述
2.1示例类文件结构
2.2示例虚拟机体系架构
2.3加载、链接和初始化
3.垃圾收集
4.加载和写入屏障
5.通过垃圾收集线程标记堆引用
6.通过应用线程加载堆引用
7.通过应用线程写入堆引用
8.通过应用线程加载已编译方法
9.其它方面;扩展
10.硬件概述
1.总体概述
一个或多个实施例包括基于垃圾收集状态(也称为“颜色”)执行垃圾收集,垃圾收集状态(a)与堆引用一起存储但(b)不与可以被用于作为应用执行的一部分访问底层对象的引用一起存储。一组垃圾收集(GC)状态被用于跟踪相对于堆引用的GC操作的进度。堆引用包括与堆引用相关联的当前GC状态的指示。基于当前GC状态和当前GC周期的当前阶段,某些GC操作被选择来处理该堆引用。同时,可以被用于作为应用执行的一部分访问底层对象的引用(也称为“可解除引用的引用”)不包括该组GC状态中的任何GC状态的任何指示。这种可解除引用的引用包括例如存储在调用堆栈(call stack)中的引用,以及嵌入在被存储在代码高速缓存(code cache)中的已编译方法(compiled method)中的引用。因此,堆存储器中的引用指示一组GC状态中的一个状态与堆引用相关联;但是存储在调用堆栈中的指向同一对象的引用不包括该组GC状态中的任何状态的任何指示。此外,堆存储器中的引用指示一组GC状态中的一个状态与堆引用相关联;但是嵌入在存储在代码高速缓存中的已编译方法中的引用不包括该组GC状态中的任何状态的任何指示。
一个或多个实施例包括在将引用从堆存储器加载到调用堆栈时实现引用加载屏障。可以与GC线程并发运行的应用线程请求将引用从堆存储器加载到调用堆栈上。该堆引用包括该堆引用的当前GC状态的指示。执行检查以确定当前GC状态相对于当前GC周期的当前阶段是否为“良好”。如果当前GC状态不为良好,那么执行一组GC操作以使堆引用从当前GC状态变为良好GC状态。该堆引用被更新以将良好GC状态指示为当前GC状态。然而,在移除GC状态的该指示之后,该引用将被存储到调用堆栈中。调用堆栈上的与该堆引用指向相同对象的引用不包括一组GC状态中的任何GC状态的指示。
一个或多个实施例包括在将引用写入到堆存储器上时实现引用写入屏障。可以与GC线程并发运行的应用线程请求将引用写入到堆存储器上。在写入到堆存储器上之前,该引用不必然包含一组GC状态中的任何GC状态的指示。确定相对于当前GC周期的当前阶段的良好GC状态。在将良好GC状态的指示添加为该引用的当前GC状态之后,将该引用写入到堆存储器上。堆存储器上的指向与要被写入的引用相同的对象的引用包括该引用的当前GC状态的指示。
一个或多个实施例包括在从代码高速缓存加载已编译方法时实现已编译方法加载屏障。可以与GC线程并发运行的应用线程请求从代码高速缓存加载已编译方法(也称为“本机方法”)。已编译方法是已从较高级语言(诸如字节码)转换成较低级语言(诸如机器码)的方法。已编译方法与如下GC状态相关联,该GC状态与嵌入在已编译方法中的一组引用牵连。已编译方法的元数据包括已编译方法的当前GC状态的指示——这隐含地是已编译方法中嵌入的该组引用的当前GC状态。执行检查以确定当前GC状态相对于当前GC周期的当前阶段是否为“良好”。如果当前GC状态不为良好,那么相对于嵌入在已编译方法中的每个引用迭代一组GC操作,以使每个引用从当前GC状态变为良好GC状态。已编译方法的元数据被更新以将良好GC状态指示为当前GC状态。然而,嵌入在已编译方法中的引用本身不包括一组GC状态中的任何GC状态的指示。
一个或多个实施例包括将引用的GC状态存储在该引用的不可寻址部分(non-addressable portion)而不是该引用的可寻址部分(addressable portion)中。在一些实施例中,硬件系统(诸如处理器)限制引用内被用于存储存储器地址的位数量(这些位在本文中称为该引用的“可寻址部分”)。可寻址部分定义了硬件系统允许的该引用可以到达的最大地址空间。在一些实施例中,硬件系统要求引用的不可寻址部分在被解除引用之前符合规范形式(canonical form)。然而,当引用未被解除引用时(诸如,当引用存储在堆存储器中时),硬件系统没有对该引用施加这样的要求。当引用未被解除引用时,引用的不可寻址部分可以被用于其它目的。鉴于一组GC状态中的GC状态被存储在堆引用中而不是可解除引用的引用中,堆引用的不可寻址部分中的某些位可以被用于存储GC状态,而可解除引用的引用的相同位可以继续符合规范形式。因此,引用的可寻址部分内的位未被指定用于存储该组GC状态,而是可以被保留用于指示该引用能够到达的最大地址空间内的唯一存储器位置。
在本说明书中描述和/或在权利要求中叙述的一个或多个实施例可能不包括在该总体概述部分中。
2.体系架构概述
图1图示了在其中可以实践本文描述的技术的示例体系架构。关于示例体系架构所描述的软件和/或硬件组件可以被省略或与与本文所描述的一组功能不同的一组功能相关联。根据一个或多个实施例,可以在环境内使用本文中未描述的软件和/或硬件组件。因此,示例环境不应当被认为是限制任何权利要求的范围。
如图1所示,计算体系架构100包括源代码文件101,源代码文件由编译器102编译成类文件103,这些类文件表示要被执行的程序。类文件103然后由执行平台112加载和执行,该执行平台包括运行时环境113、操作系统111以及使得能够在运行时环境113和操作系统之间通信的一个或多个应用编程接口(API)110。运行时环境113包括虚拟机104,该虚拟机包括各种组件,诸如存储器管理器105(其可以包括垃圾收集器)、用于检查类文件103的有效性的类文件验证器106、用于定位和构建类的存储器中表示(in-memoryrepresentation)的类加载器107、用于执行虚拟机104代码的解释器108以及用于产生经优化的机器级别代码的即时(just-in-time,JIT)编译器109。
在实施例中,计算体系架构100包括源代码文件101,源代码文件包含已经用特定编程语言(诸如Java、C、C++、C#、Ruby、Perl等)编写的代码。因此,源代码文件101遵循用于该相关联的语言的一组特定语法和/或语义规则。例如,用Java编写的代码遵循Java语言规范。然而,由于规范随着时间的推移被更新和修订,因此源代码文件101可能与指示源代码文件101所遵循的规范的修订版本的版本号相关联。被用于编写源代码文件101的确切编程语言通常不是关键的。
在各种实施例中,编译器102将根据针对程序员的便利性的规范所编写的源代码转换为可由特定机器环境直接执行的机器或目标代码,或者可由能够在各种特定机器环境之上运行的虚拟机104执行的中间表示(“虚拟机代码/指令”)(诸如字节码)。虚拟机指令可由虚拟机104以比源代码更直接和高效的方式执行。将源代码转换为虚拟机指令包括将源代码功能从该语言映射到利用底层资源(诸如数据结构)的虚拟机功能。通常,由程序员经由源代码以简单术语呈现的功能被转换为更复杂的步骤,这些步骤更直接地映射到虚拟机104所驻留的底层硬件所支持的指令集。
一般而言,程序作为经编译的程序或者经解释的程序来执行。当程序被编译时,代码在执行之前从第一语言全局地变换为第二语言。由于变换代码的工作是提前执行的,所以经编译的代码往往具有优异的运行时性能。此外,由于该变换在执行之前全局地发生,因此可以使用诸如常量合并(constant folding)、死代码消除(dead code elimination)、内联(inlining)等技术来分析和优化该代码。然而,取决于被执行的程序,启动时间(start-up time)可能很长。此外,插入新代码将需要使程序下线(offline)、重新编译和重新执行。对于被设计为允许代码在程序执行期间被插入的许多动态语言(诸如Java),纯编译的方法可能是不合适的。当程序被解释时,程序的代码在程序执行的同时被逐行读取并且转换为机器级别指令。因此,程序具有短的启动时间(可以几乎立即开始执行),但是运行时性能由于在工作中(on the fly)执行变换而降低。此外,由于每个指令被单独地分析,因此依赖于对程序的更全局分析的许多优化不能被执行。
在一些实施例中,虚拟机104包括解释器108和JIT编译器109(或实现这两个方面的组件),并且使用解释技术和编译技术的组合来执行程序。例如,虚拟机104可以初始地通过经由解释器108解释表示程序的虚拟机指令来开始,同时跟踪与程序行为相关的统计信息,诸如不同的代码部分或代码块多频繁地被虚拟机104执行。一旦代码块超过阈值(变“热”),虚拟机104就调用JIT编译器109来执行对该块的分析并且生成经优化的机器级别指令,这些经优化的机器级别指令代替“热”代码块被用于将来的执行。由于程序往往花费大部分时间执行整个代码的一小部分,因此只编译程序的“热”部分可以提供与完全编译代码相似的性能,但没有启动惩罚。此外,尽管优化分析被约束到“热”块被代替,但是仍然存在比单独转换每个指令大得多的优化潜力。在上述示例中存在多种变体,诸如分层编译。
为了提供清楚的示例,源代码文件101已经被图示为要由执行平台112执行的程序的“顶级”表示。虽然计算体系架构100将源代码文件101绘为“顶级”程序表示,但是在其它实施例中,源代码文件101可以是经由将不同语言的代码文件处理成源代码文件101的语言的“更高级”编译器接收到的中间表示。以下公开中的一些示例假设源代码文件101遵循基于类的面向对象的编程语言。然而,这不是对利用本文所描述的特征的要求。
在实施例中,编译器102接收源代码文件101作为输入,并且将源代码文件101转换为以虚拟机104所期望的格式的类文件103。例如,在JVM的上下文中,Java虚拟机规范定义了类文件103预期要遵循的特定类文件格式。在一些实施例中,类文件103包含已从源代码文件101转换的虚拟机指令。然而,在其它实施例中,类文件103也可以包含其它结构,诸如识别常量值的表和/或与各种结构(类、字段、方法等)相关的元数据。
以下讨论假设类文件103中的每一个类文件表示在源代码文件101中定义的(或由编译器102/虚拟机104动态生成的)相应的“类”。然而,前述假设不是严格的要求并且将取决于虚拟机104的实现方式。因此,无论类文件103的确切格式如何,本文描述的技术都仍然可以被执行。在一些实施例中,类文件103被划分为一个或多个“库(libraries)”或“包(package)”,其中的每一个库或包包括提供相关功能的类的集合。例如,库可以包含实现输入/输出(I/O)操作、数学工具、密码技术、图形实用工具等的一个或多个类文件。此外,一些类(或这些类中的字段/方法)可以包括访问限制,这些访问限制将类的使用限制在特定类/库/包内或限制到具有适当权限的类。
2.1示例类文件结构
图2图示了根据实施例的以框图形式的类文件200的示例结构。为了提供清楚的示例,本公开的其余部分假设计算体系架构100的类文件103遵循本部分中所描述的示例类文件200的结构。然而,在实际环境中,类文件200的结构将取决于虚拟机104的实现方式。此外,本文所讨论的一个或多个特征可以修改类文件200的结构,以例如添加附加的结构类型。因此,类文件200的确切结构对于本文描述的技术不是关键的。为了第2.1部分的目的,“类”或“当前类”是指由类文件200表示的类。
在图2中,类文件200包括常量表201、字段结构208、类元数据207和方法结构209。在实施例中,常量表201是除了其它功能之外还充当类的符号表的数据结构。例如,常量表201可以存储与在源代码文件101中使用的各种标识符相关的数据,诸如类型、范围、内容和/或位置。常量表201具有用于值结构202(表示类型int、long、double、float、byte、string等的常量值)、类信息结构203、名称和类型信息结构204、字段引用结构205、以及由编译器102从源代码文件101导出的方法引用结构206的条目。在实施例中,常量表201被实现为将索引i映射到结构j的数组。然而,常量表201的确切实现不是关键的。
在一些实施例中,常量表201的条目包括对其它常量表201条目进行索引的结构。例如,用于表示串的值结构202之一的条目可以保持将其“类型”识别为串的标签以及如下索引,该索引指向存储表示该串的ASCII字符的char、byte或int值的常量表201的一个或多个其它值结构202。
在实施例中,常量表201的字段引用结构205在常量表201中保持指向表示定义字段的类的类信息结构203之一的索引,以及在常量表201保持指向提供字段的名称和描述符的名称和类型信息结构204之一的索引。常量表201的方法引用结构206在常量表201中保持指向表示定义方法的类的类信息结构203之一的索引,以及在常量表201中保持指向提供方法的名称和描述符的名称和类型信息结构204之一的索引。类信息结构203在常量表201中保持指向保持相关联的类的名称的值结构202之一的索引。
名称和类型信息结构204在常量表201中保持指向存储字段/方法的名称的值结构202之一的索引,以及在常量表201中保持指向存储描述符的值结构202之一的索引。
在实施例中,类元数据207包括类的元数据,诸如(一个或多个)版本号、常量池中的条目数量、字段数量、方法数量、访问标志(类是否是公开的(public)、私有的(private)、最终的(final)、抽象的(abstract)等)、指向识别当前类的常量表201的类信息结构203之一的索引、指向识别超类(superclass)(如果有的话)的常量表201的类信息结构203之一的索引,等等。
在实施例中,字段结构208表示识别类的各种字段的一组结构。字段结构208为类的每个字段存储该字段的访问器标志(字段是否是静态的(static)、公开的(public)、私有的(private)、最终的(final)等)、在常量表201中指向保持该字段的名称的值结构202之一的索引、以及在常量表201中指向保持该字段的描述符的值结构202之一的索引。
在实施例中,方法结构209表示识别类的各种方法的一组结构。方法结构209为类的每个方法存储该方法的访问器标志(例如,方法是否是静态的(static)、公开的(public)、私有的(private)、同步的(synchronized)等)、在常量表201中指向保持方法的名称的值结构202之一的索引、在常量表201中指向保持方法的描述符的值结构202之一的索引、以及与在源代码文件101中定义的方法的主体对应的虚拟机指令。
在实施例中,描述符表示字段或方法的类型。例如,描述符可以实现为遵循特定语法的串。虽然确切的语法不是重要的,但以下将描述几个示例。
在描述符表示字段的类型的示例中,描述符识别由该字段保持的数据的类型。在实施例中,字段可以保持基本类型、对象或数组。当字段保持基本类型时,描述符是识别该基本类型的串(例如,“B”=byte、“C”=char、“D”=double、“F”=float、“I”=int、“J”=long int等)。当字段保持对象时,描述符是识别该对象的类名称(例如,“L ClassName”)的串。在这种情况下,“L”指示引用,因此“L ClassName”表示对类ClassName的对象的引用。当字段是数组时,描述符识别由该数组保持的类型。例如,“[B”指示字节的数组,其中“[”指示数组并且“B”指示数组保持基本字节类型。然而,由于数组可以嵌套,因此数组的描述符也可以指示嵌套。例如,“[[L ClassName”指示如下数组,其中每个索引保持保持类ClassName的对象的数组。在一些实施例中,ClassName是完全限定的,并且包括该类的简单名称以及该类的路径名。例如,ClassName可以指示文件被存储在包、库或托管类文件200的文件系统中的什么位置。
在方法的情况下,描述符识别方法的参数和方法的返回类型。例如,方法描述符可以按照一般形式“({Parameter Descriptor})ReturnDescriptor”,其中{ParameterDescriptor}是表示参数的字段描述符的列表,并且ReturnDescriptor是识别返回类型的字段描述符。例如,串“V”可以被用于表示void返回类型。因此,在源代码文件101中定义为“Object m(int I,double d,Thread t){...}”的方法与描述符“(I D LThread)L Object”匹配。
在实施例中,保持在方法结构209中的虚拟机指令包括引用常量
表201的条目的操作。使用Java作为示例,考虑以下类:
在以上示例中,Java方法add12and13在类A中定义,不带参数,并且返回整数(integer)。方法add12and13的主体调用类B的静态方法addTwo,该静态方法采用常整数值12和13作为参数,并且返回结果。因此,在常量表201中,编译器102除其它条目之外还包括与对方法B.addTwo的调用对应的方法引用结构。在Java中,对方法的调用向下编译为JVM的字节码中的invoke命令(在这种情况下为invokestatic,因为addTwo是类B的静态方法)。该invoke命令被提供常量表201中与方法引用结构对应的索引,该方法引用结构识别定义addTwo“B”的类、addTwo的名称“addTwo”、以及addTwo的描述符“(I I)I”。例如,假设上述方法引用被存储在索引4处,则字节码指令可以表现为“invokestatic#4”。
由于常量表201使用携带识别信息的结构来符号地引用类、方法和字段而不是直接引用存储器位置,因此常量表201的条目被称为“符号引用”。符号引用被用于类文件103的一个原因是因为在一些实施例中一旦类被加载到运行时环境113中,编译器102就不知道类将如何被存储以及存储在哪里。如将在2.3部分中所描述的,在所引用的类(及相关联的结构)已被加载到运行时环境中并且被分配具体的存储器位置之后,符号引用的运行时表示会最终地被虚拟机104解析为实际的存储器地址。
2.2示例虚拟机体系架构
图3图示了根据实施例的以框图形式的示例虚拟机存储器布局300。为了提供清楚的示例,其余的讨论将假设虚拟机104遵循图3中绘出的虚拟机存储器布局300。此外,虽然虚拟机存储器布局300的组件可以被称为存储器“区域”,但是不要求存储器区域是连续的。
在图3图示的示例中,虚拟机存储器布局300被划分为共享区域301和线程区域307。共享区域301表示虚拟机104上执行的各种线程之间共享的结构被存储的存储器中的区域。共享区域301包括堆302和按类(per-class)区域303。在实施例中,堆302表示从中分配用于类实例和数组的存储器的运行时数据区域。在实施例中,按类区域303表示在其中存储与单个类有关的数据的存储区域。在实施例中,对于每个加载的类,按类区域303包括表示来自该类的常量表201的数据的运行时常量池304、字段和方法数据306(例如,以保持该类的静态字段)、以及表示用于该类的方法的虚拟机指令的方法代码305。
线程区域307表示存储特定于各个线程的结构的存储器区域。在图3中,线程区域307包括线程结构308和线程结构311,其表示由不同线程利用的按线程(per-thread)结构。为了提供清楚的示例,图3中绘出的线程区域307假设两个线程正在虚拟机104上执行。然而,在实际环境中,虚拟机104可以执行任何任意数量的线程,其中线程结构的数量相应地缩放。
在实施例中,线程结构308包括程序计数器309和虚拟机堆栈310。类似地,线程结构311包括程序计数器312和虚拟机堆栈313。在实施例中,程序计数器309和程序计数器312存储正由它们的相应的线程执行的虚拟机指令的当前地址。
因此,当线程逐步通过指令时,程序计数器被更新以维持指向当前指令的索引。在实施例中,虚拟机堆栈310和虚拟机堆栈313各自存储用于其相应线程的帧(frame),该帧保持局部变量和部分结果并且还被用于方法调用和返回。
在实施例中,帧是被用于存储数据和部分结果、返回方法的值、以及执行动态链接的数据结构。每次调用方法时创建新帧。当使得生成帧的方法完成时,该帧被销毁。因此,当线程执行方法调用时,虚拟机104生成新帧并将该帧推送到与该线程相关联的虚拟机堆栈上。
当方法调用完成时,虚拟机104将方法调用的结果传递回到前一帧,并将当前帧从堆栈中弹出。在实施例中,对于给定的线程,在任何点处一个帧是活动的。此活动帧被称为当前帧,使得生成类当前帧的方法被称为当前方法,并且当前方法所属的类被称为当前类。
图4图示了根据实施例的以框图形式的示例帧400。为了提供清楚的示例,其余的讨论将假设虚拟机堆栈310和虚拟机堆栈313的帧遵守帧400的结构。
在实施例中,帧400包括局部变量401、操作数堆栈402和运行时常量池引用表403。在实施例中,局部变量401被表示为变量数组,每个变量保持值,例如,Boolean、byte、char、short、int、float或reference值。此外,一些值类型(诸如long或double)可以由数组中的多于一个的条目表示。局部变量401被用于在方法调用上传递参数并存储部分结果。例如,当响应于调用方法而生成帧400时,参数可以被存储在局部变量401内的预定位置中,诸如与该调用中的第一至第N个参数对应的索引1-N。
在实施例中,当虚拟机104创建帧400时,操作数堆栈402默认为空。然后,虚拟机104从当前方法的方法代码305中供给指令以将来在局部变量401的常量或值加载到操作数堆栈402上。其它指令从操作数堆栈402获取操作数、对其进行操作、并将结果推送回到操作数堆栈402上。此外,操作数堆栈402被用于准备要传递给方法的参数和接收方法结果。例如,正被调用的方法的参数可以在向方法发出调用之前被推送到操作数堆栈402上。然后,虚拟机104为该方法调用生成新帧,其中前一帧的操作数堆栈402上的操作数被弹出并被加载到该新帧的局部变量401中。当被调用的方法终止时,新帧从虚拟机堆栈中弹出并且返回值被推送到前一帧的操作数堆栈402上。
在实施例中,运行时常量池引用表403包含对当前类的运行时常量池304的引用。运行时常量池引用表403被用于支持解析。解析是将常量池304中的符号引用转换成具体的存储器地址的处理,从而根据需要加载类以解析尚未定义的符号并将变量访问转换成与这些变量的运行时位置相关联的存储结构中的适当偏移量。
2.3加载、链接和初始化
在实施例中,虚拟机104动态地加载、链接和初始化类。加载是找到具有特定名称的类并在运行时环境113的存储器内从该类的相关联类文件200创建表示的处理。例如,在虚拟机存储器布局300的按类区域303内为该类创建运行时常量池304、方法代码305以及字段和方法数据306。链接是取得类的存储器中表示并将其与虚拟机104的运行时状态组合使得该类的方法可以被执行的处理。初始化是执行类构造函数(constructor)以设置类的字段和方法数据306的开始状态和/或在堆302上创建用于经初始化的类的类实例的处理。
以下是可以由虚拟机104实现的加载、链接和初始化技术的示例。然而,在许多实施例中,这些步骤可以被交错,使得初始类被加载,然后在链接期间,第二个类被加载以解析在第一个类中找到的符号引用,这又导致第三个类被加载,等等。因此,通过加载、链接和初始化阶段的进度可以因类而异。此外,一些实施例可以延迟(“懒惰”执行)加载、链接和初始化处理的一个或多个功能,直到实际上需要该类。例如,对方法引用的解析可以被延迟,直到调用该方法的虚拟机指令被执行。因此,对于每个类,执行步骤的确切时间在各种实现方式之间会有很大不同。
为了开始加载处理,虚拟机104通过调用加载初始类的类加载器107来启动。指定初始类的技术将在实施例之间不同。例如,一种技术可以使虚拟机104在启动时接受指定初始类的命令行变元。
为了加载类,类加载器107解析与该类对应的类文件200,并且确定类文件200是否是良好构造的(满足虚拟机104的句法期望)。如果不是,则类加载器107生成错误。例如,在Java中,错误可能以异常的形式生成,其中异常被抛出给异常处理器进行处理。否则,类加载器107通过在按类区域303内为该类分配运行时常量池304、方法代码305以及字段和方法数据306来生成该类的存储器中表示。
在一些实施例中,当类加载器107加载类时,类加载器107还递归加载该被加载类的超类。例如,虚拟机104可以确保在继续特定类的加载、链接和初始化处理之前,该特定类的超类被加载、链接和/或初始化。
在链接期间,虚拟机104验证类、准备类、并且执行在类的运行时常量池304中定义的符号引用的解析。
为了验证类,虚拟机104检查类的存储器中表示是否在结构上正确。例如,虚拟机104可以检查除通用类Object之外的每个类具有超类、检查最终类没有子类以及最终方法没有被覆盖、检查常量池条目是否彼此一致、检查当前类是否具有对常量池304中引用的类/字段/结构的正确访问权限、检查方法的虚拟机104代码将不会引起意外行为(例如,确保跳转指令不会将虚拟机104发送到超出该方法的结束范围),等等。在验证期间执行的确切检查取决于虚拟机104的实现方式。在一些情况下,验证会导致附加的类被加载,但不一定要求那些类在继续之前也被链接。例如,假设类A包含对类B的静态字段的引用。在验证期间,虚拟机104可以检查类B,以确保被引用的静态字段实际上存在,这可能导致类B的加载,但不一定导致类B的链接或初始化。然而,在一些实施例中,某些验证检查可以被一直延迟到以后的阶段,诸如在符号引用的解析期间被检查。例如,一些实施例可以延迟检查对符号引用的访问许可,直到这些引用被解析。
为了准备类,虚拟机104将位于类的字段和方法数据306内的静态字段初始化为默认值。在某些情况下,将静态字段设置为默认值可能与运行类的构造函数不同。例如,验证处理可以将静态字段清零或将其设置为构造函数期望这些字段在初始化期间具有的值。
在解析期间,虚拟机104从包括在类的运行时常量池304中的符号引用动态地确定具体的存储器地址。为了解析符号引用,虚拟机104利用类加载器107加载在符号引用中识别出的类(如果尚未加载)。一旦被加载,虚拟机104就知道所引用类及其字段/方法在按类区域303内的存储器位置。然后,虚拟机104用对所引用类、字段或方法的具体存储器位置的引用来替换符号引用。在实施例中,虚拟机104将解析进行高速缓存,以在当虚拟机104处理另一个类时遇到相同类/名称/描述符的情况下进行重用。例如,在一些情况下,类A和类B可能调用类C的同一方法。因此,当对类A执行解析时,该结果可以被高速缓存,并且在解析类B中的相同符号引用期间被重用,以减少开销。
在一些实施例中,在链接期间解析符号引用的步骤是可选的。例如,实施例可以以“懒惰”的方式执行符号解析,从而将解析的步骤延迟直到需要所引用类/方法/字段的虚拟机指令被执行。
在初始化期间,虚拟机104执行类的构造函数以设置该类的开始状态。例如,初始化可以初始化类的字段和方法数据306并且在堆302上生成/初始化由构造函数创建的任何类实例。例如,用于类的类文件200可以指定特定方法是用于设置开始状态的构造函数。因此,在初始化期间,虚拟机104执行该构造函数的指令。
在一些实施例中,虚拟机104通过初始地检查字段/方法是否在引用的类中被定义来执行对字段和方法引用的解析。否则,虚拟机104针对所引用字段/方法递归地搜索所引用类的超类,直到定位该字段/方法或者到达顶级超类(在这种情况下生成错误)。
3.垃圾收集
图5图示了根据实施例的虚拟机的执行引擎和堆存储器。如图5中所示,系统500包括执行引擎502和堆530。系统500可以包括比图5中所示的组件更多或更少的组件。图5中所示的组件可以彼此在本地或远离。
在一个或多个实施例中,堆530表示运行时数据区域,从该运行时数据区域中分配用于类实例和数组的存储器。堆530的示例在上面被描述为图3中的堆302。
堆530存储在应用执行期间创建的对象534a-534d。存储在堆510中的对象可以是普通对象、对象数组或另一类型的对象。普通对象是类实例。类实例是由类实例创建表达式显式创建的。对象数组是容器对象,它保持固定数量的单一类型的值。对象数组是特定的一组普通对象。
堆530存储存活对象534b、534d(由虚线图案指示)和不使用的对象534a、534c(也称为“死对象”,由空白图案指示)。不使用的对象是不再被任何应用使用的对象。存活对象是仍在被至少一个应用使用的对象。如果对象(a)被根引用指向(这将在下面针对图8的根引用820进一步描述)或(b)可从由根引用所指向的另一个对象追踪,那么该对象仍在被应用使用。如果对第一对象的引用被包含在第二对象中,那么第一对象从第二对象“可追踪”。
样本代码可以包括以下内容:
执行上述样本代码的应用线程508a在堆530中创建对象temp。对象temp是Person类型,并且包括两个字段。由于字段age是整数,堆530的分配给temp的部分直接存储字段age的值“3”。由于字段name是串,因此堆530的分配给temp的部分不直接存储name字段的值;而是堆530的分配给temp的部分存储对另一个String类型对象的引用。该String对象存储值“Sean”。该String对象被称为从Person对象“可追踪”。
在一个或多个实施例中,执行引擎502包括被配置为执行各种操作的一个或多个线程。如图所示,例如,执行引擎502包括垃圾收集(GC)线程506a-b和应用线程508a-b。
在一个或多个实施例中,应用线程508a-b被配置为执行一个或多个应用的操作。应用线程508a-b在运行时期间创建对象,这些对象存储在堆530上。应用线程508a-b也可以被称为“突变器(mutator)”,因为应用线程508a-b可以使堆530突变(在GC周期的并发阶段期间和/或在GC周期之间)。
在一个或多个实施例中,GC线程506a-b被配置为执行垃圾收集。GC线程506a-b基于调度和/或事件触发器(诸如当达到堆(或其区段(region))的阈值分配时)迭代地执行GC周期。GC周期包括一组GC操作,这些操作用于回收堆中被不使用的对象所占用的存储器位置。
在实施例中,多个GC线程504a-b可以并行地执行GC操作。并行工作的该多个GC线程504a-b可以被称为“并行收集器”。
在实施例中,GC线程504a-b可以与应用线程508a-b的执行并发地执行至少一些GC操作。与应用线程508a-b并发操作的GC线程504a-b可以被称为“并发收集器”或“部分并发收集器”。
在实施例中,GC线程504a-b可以执行分代(genrerational)垃圾收集。堆被分成不同的区段。第一区段(可以被称为“年轻代空间”)存储尚未满足从第一区段提升到第二区段的标准的对象;第二区段(可以被称为“老龄代空间”)存储已满足从第一区段提升到第二区段的标准的对象。例如,当存活对象生存至少阈值数量的GC周期时,该存活对象就从年轻代空间提升到老龄代空间。
用于执行垃圾收集的各种不同的GC处理实现不同的存储器效率、时间效率和/或资源效率。在实施例中,可以针对不同的堆区段执行不同的GC处理。作为示例,堆可以包括年轻代空间和老龄代空间。可以对年轻代空间执行一种类型的GC处理。可以为老龄代空间执行不同类型的GC处理。
下面描述不同GC处理的示例。作为示例,复制收集器(copying collector)涉及堆的至少两个单独定义的地址空间,称为“源空间(from-space)”和“目标空间(to-space)”。复制收集器识别存储在被定义为源空间的区域内的存活对象。复制收集器将存活对象复制到被定义为目标空间的另一个区域。在识别并复制所有存活对象之后,定义为源空间的区域被回收。新的存储器分配可以从原始源空间的第一个位置开始。
复制可以在堆内至少三个不同的区段完成:一个伊甸园空间(Eden space)以及两个生存者空间(survivor space)S1和S2。对象最初分配在伊甸园空间中。当伊甸园空间已满时,会触发GC周期。存活对象从伊甸园空间被复制到生存者空间之一,例如S1。在下一个GC周期,伊甸园空间中的存活对象被复制到另一个生存者空间,这将是S2。此外,S1中的存活对象也被复制到S2。
作为另一个示例,标记和清扫(mark-and-sweep)收集器将GC操作分为至少两个阶段:标记阶段和清扫阶段。在标记阶段期间,标记和清扫收集器用“存活”位标记每个存活对象。例如,该存活位可以是存活对象的对象标头内的位。在清扫阶段期间,标记和清扫收集器遍历堆以识别连续存储器地址空间的所有未标记块。标记和清扫收集器将未标记的块链接在一起,形成有组织的空闲列表。这些未标记的块被回收。使用这些空闲列表来执行新的存储器分配。新对象可以被存储在从空闲列表中识别出的存储器块中。
标记和清扫收集器可以被实现为并行收集器。附加地或替代地,标记和清扫收集器可以被实现为并发收集器。并发标记和清扫收集器的GC周期中的示例阶段包括:
阶段1:识别根引用所引用的对象(这与正在执行的应用不是并发的)
阶段2:标记从根引用所引用的对象可到达的对象(这可以是并发的)
阶段3:识别在阶段2期间已作为程序执行的一部分被修改的对象(这可以是并发的)
阶段4:重新标记在阶段3标识出的对象(这不是并发的)
阶段5:清扫堆以获得空闲列表并回收存储器(这可以是并发的)
作为另一个示例,压缩收集器尝试对回收的存储器区域进行压缩。堆被分区为一组大小相等的堆区段,每个区段是虚拟存储器的连续范围。压缩收集器执行并发的全局标记阶段以确定整个堆中对象的存活度(liveness)。在标记阶段完成之后,压缩收集器识别大部分为空的区段。压缩收集器首先收集这些区段,这通常会产生大量的空闲空间。压缩收集器将其收集和压缩活动集中在堆中的可能充满可回收对象(即垃圾)的区域。压缩收集器将存活对象从堆的一个或多个区段复制到堆上的单个区段,并在该处理中压缩和释放存储器。这种清除(evacuation)可以在多处理器上并行执行,以减少暂停时间并增加吞吐量。
并发压缩收集器的GC周期内的示例阶段包括:
阶段1:识别根引用所引用的对象(这与正在执行的应用不并发)
阶段2:标记从根引用所引用的对象可到达的对象(这可以是并发的)
阶段3:识别在阶段2期间已作为程序执行的一部分被修改的对象(这可以是并发的)
阶段4:重新标记在阶段3处标识出的对象(这不是并发的)
阶段5:将存活对象从源区段复制到目的地区段,从而回收源区段的存储器空间(这不是并发的)
作为另一个示例,加载屏障收集器标记并压缩存活对象,但懒惰地对指向重新定位对象的引用进行重新映射。加载屏障收集器依赖于嵌入存储在堆上的引用内的“颜色”。颜色表示GC状态,并跟踪相对于引用的GC操作的进度。颜色是通过存储在引用的某些位内的元数据捕获的。
在时间的每时每刻,所有GC线程506a-b就什么颜色是“良好颜色”或“良好GC状态”达成一致。将引用从堆530加载到调用堆栈的GC线程506a-b首先应用检查以确定该引用的当前颜色是否良好。类似地,将引用从堆530加载到调用堆栈的应用线程508a-b首先应用检查以确定该引用的当前颜色是否良好。该检查可以被称为“加载屏障”。颜色良好的引用将命中快速路径,快速路径不会产生附加工作。否则,该引用将命中慢速路径。慢速路径涉及某些GC操作,这些操作将引用从当前GC状态带入良好GC状态。该引用在堆530中所驻留的槽被更新为带有颜色良好的别名(good-colored alias),以避免随后命中慢速路径(更新为良好颜色也可以被称为“自我修复”)。
例如,陈旧的引用(对在压缩期间已并发移动的对象的引用,这意味着地址可能指向该对象的过时副本,或另一个对象,或者甚至什么也没有)被保证没有良好颜色。尝试从堆加载引用的应用线程首先执行加载屏障。通过加载屏障,引用被识别为陈旧(不是良好颜色)。该引用因此被更新为指向对象的新位置并且与良好颜色相关联。具有经更新的地址和良好颜色的引用被存储到堆中。具有经更新的地址的引用也可以被返回给应用线程。然而,返回给应用线程的引用不必然包含任何颜色。
可以使用与上述那些GC处理不同的附加和/或替代类型的GC处理。其它类型的GC处理也可能依赖于引用的“颜色”,或者与存储在引用内的垃圾收集相关的元数据。
在实施例中,颜色与堆引用一起存储,但不与可解除引用的引用一起存储。术语“堆引用”是指存储在堆530上的引用。术语“可解除引用的引用”是指执行引擎用来访问引用所指向的对象的值的引用。获得引用所指向的对象的值被称为对该引用“解除引用”。尝试对存储在堆530上的引用解除引用的GC线程506a-b首先将该引用从堆530加载到GC线程506a-b的调用堆栈。尝试对存储在堆530上的引用解除引用的应用线程508a-b首先将该引用从堆530加载到应用线程508a-b的调用堆栈。(例如,应用线程将引用加载到调用堆栈的帧400内的局部变量401中,如上文参考图4所述)。堆引用和/或可解除引用的引用在本文中被一般地称为“引用”。”
参考图6,图6图示了根据实施例的堆引用和可解除引用的引用。引用可以包括任意数量的位,这取决于计算环境。例如,在Intel x86-64机器中,引用有64位。
在实施例中,可解除引用的引用601包括不可寻址部分602和可寻址部分604。可寻址部分604定义引用601可以到达的最大地址空间。取决于应用在其上执行的硬件系统,不可寻址部分602可能被需要,以在引用601被解除引用之前遵守规范形式。如果施加了这样的要求,那么硬件系统(诸如处理器)在尝试对不兼容的可解除引用的引用解除引用时会生成错误。因此,引用601的不可寻址部分602不能被用于存储任何与GC相关的元数据,诸如GC状态。例如,在Intel x86-64机器中,引用的可寻址部分有48位,不可寻址部分有16位。基于硬件施加的限制,该引用最多可以到达248个唯一地址。规范形式要求不可寻址部分是存储在可寻址部分中的值的符号扩展611(即,高阶的位48至63必须是存储在位47中的值的副本)。
如图所示,可寻址部分604包括地址620和可选的其它位618。地址620是指引用600所指向的对象的地址。其它位618可以是未使用的。替代地,其它位618可存储元数据,其可能但不必然与垃圾收集相关。
如上所述,可解除引用的引用601包括存储在调用堆栈上的引用。附加地或替代地,可解除引用的引用601包括嵌入在存储在代码高速缓存和/或其它存储器位置上的已编译方法内的引用。已编译方法是已从高级语言(诸如字节码)转换成低级语言(诸如机器码)的方法。应用线程可以直接访问代码高速缓存或其它存储器位置内的已编译方法,以执行该已编译方法。作为示例,已编译方法可以由图1的JIT编译器109生成。作为另一个示例,已编译方法可以由虚拟机的另一个组件生成。
在实施例中,堆引用600包括相同的不可寻址部分602和可寻址部分604。然而,不可寻址部分602不必然符合规范形式。如图所示,堆引用600的不可寻址部分602包括瞬态颜色606和可选的其它位610。瞬态颜色606表示如下GC状态,该状态跟踪相对于引用600的GC操作的进度。颜色606是“瞬态的”,因为当引用从堆530加载到调用堆栈时,颜色606不需要与该引用保持在一起。其它位610可以是未使用的。替代地,其它位610可以存储元数据,这些元数据可以但不必然与垃圾收集相关。
在实施例中,瞬态颜色606包括M0、M1和重新映射(Remap)。在实施例中,每个颜色由堆引用600内的位表示。位M0 616表示M0GC状态。位M1 614表示M1 GC状态。位R 612表示重新映射GC状态。在任何时间点设置M0 616、M1 614、R 612中的仅一个来指示堆引用600的当前GC状态。在另一个实施例中,瞬态颜色606M0、M1和重新映射以不同方式在堆引用600内表达。下面参考图7-8进一步详细解释颜色M0、M1和重新映射。在又一个实施例中,瞬态颜色606可以表示一组不同的GC状态全体。瞬态颜色606可以表示在附加和/或替代类型的GC处理中使用的GC状态。
在实施例中,(不可寻址部分602内的)瞬态颜色606表示一组GC状态,而(可寻址部分604内的)其它位618表示另一组GC状态。瞬态颜色606可以表示一组互斥的GC状态(诸如,M0、M1和R)中的一个,而其它位618可以表示与该组互斥的GC状态不互斥的一个或多个其它GC状态。其它位618可以跟踪例如引用的年龄(age)。
图7图示了根据实施例的垃圾收集周期。GC周期700包括以下阶段:标记开始702、标记/重新映射704、标记结束706、清除选择708、重新定位开始710和重新定位712。在上述阶段中,以下是非并发的阶段(由六边形指示):标记开始702、标记结束706和重新定位开始710。全部应用线程508a-b必须在非并发阶段期间暂停(也称为“停止世界暂停(stop-theworld pause)”或“STW暂停”)。以下是并发的阶段(由矩形指示):标记/重新映射704、清除选择708和重新定位712。各阶段的详细讨论如下。还可以在每个阶段中执行除了下面讨论的操作之外的附加和/或替代操作。
标记开始702(STW)。GC周期以STW暂停开始。在标记开始702期间,M0或M1之一被选为“良好颜色”。如果在当前GC周期700期间选择M0作为良好颜色,那么在下一个GC周期的标记开始阶段期间选择M1作为良好颜色。如果M0是当前良好颜色,那么M0被称为“当前标记位”,并且M1被称为“旧标记位”。在标记开始702期间,一个或多个GC线程506a-b识别所有根引用。
标记/重新映射704(并发)。在标记开始702之后,GC线程506a-b执行对对象图的遍历以识别和标记所有存活对象。如果在此处理期间在堆530中发现陈旧引用,那么用该引用所引用的对象的当前地址来更新该引用。堆530中的该引用还被更新以指示良好颜色。这保证在标记/重新映射704完成之后堆中没有保留陈旧引用。
可选地,记录每页存活度信息(每个存储器页上存活对象的总数和总大小)。在清除选择708期间,可以使用存活度信息来选择供清除的页面。
标记结束706(STW)。GC线程506a-b确认标记已完成。
清除选择708(并发)。GC线程506a-b选择存储器的页面(或其它部分)以供清除。GC线程506a-b可以基于在标记/重新映射704期间记录的每页存活度信息来选择清除页面。
重新定位开始710(STW)。在重新定位开始710期间,良好颜色改变为R,这有效地使所有引用无效。GC线程506a-b对存储在清除页面中的由根引用指向的所有对象进行重新定位。GC线程506a-b将对象重新定位到一个或多个目的地区段。在实施例中,GC线程506a-b选择空区段作为重新定位的对象的目的地。在另一个实施例中,可以使用附加的和/或替代的方法来为重新定位的对象选择目的地。GC线程506a-b还重新映射所有根引用。一个或多个转发表(诸如每页转发表)被用于记录从旧地址到新地址的映射。这些转发表在访问过时引用时被应用线程508a-b咨询,或者在下一个GC周期的标记/重新映射604期间被GC线程506a-b咨询(如果没有应用线程508a-b已访问过时引用的话)。
重新定位712(并发)。GC线程506a-b重新定位存储在清除页面中的剩余存活对象。GC线程506a-b将对象重新定位到一个或多个目的地区段。对重新定位对象的引用因此变得陈旧。如上文引用重新定位开始710所述,一个或多个转发表(诸如每页转发表)被用于记录从旧地址到新地址的映射。这些转发表在访问过时引用时被应用线程508a-b咨询,或者在下一个GC周期的标记/重新映射604期间被GC线程506a-b咨询(如果没有应用线程508a-b已访问过时引用的话)。
图8A-8D图示了根据实施例的垃圾收集处理。在示例中,引用包括24位。低阶的16位指示对象的地址。第17位指示M0,第18位指示M1,第19位指示R,剩余位是未使用的。因此,例如,指示地址1234(十六进制)和颜色R的引用将是“041234”(十六进制)。同样在这个示例中,堆830包括区段832a-c。堆830存储对象834a-g。
在示例中,坏位掩码800被维护。坏位掩码800指示当前的良好颜色。在实施例中,坏位掩码800的值仅在与坏颜色对应的位位置中具有1,而在所有剩余位中具有0。例如,如果良好颜色是R,那么坏位掩码将是“030000”(十六进制,“1”用于M0和M1位(坏颜色),并且“0”用于所有剩余位)。
坏位掩码800可以被存储在一个或多个存储器位置以确保所有GC线程和/或应用线程的可访问性。特定的存储器位置取决于软件和/或硬件计算环境。在实施例中,坏位掩码800的副本被存储在每个线程的相应线程局部变量中。因此,每个线程都可以通过该线程自己的线程局部变量来访问坏位掩码800。当更改坏位掩码800时,每个线程局部变量被更新。在另一个实施例中,坏位掩码800被嵌入到代码流中。每个引用加载屏障包括如下指令,该指令(a)指定坏位掩码的值,以及(b)将坏位掩码的指定值存储到临时寄存器中。线程访问该临时寄存器以获得坏位掩码。已编译方法加载屏障(诸如图12的方法加载屏障1210)在指令序列中定位指定坏位掩码的值的每个这样的指令。已编译方法加载屏障基于当前GC阶段的良好颜色而修补由此类指令指示的坏位掩码的值。已编译方法加载屏障可以使用交叉修改代码(cross modifying code)来制作该补丁。在另一个实施例中,坏位掩码的值被存储在所有线程都可访问的特定寄存器中。在STW阶段期间,基于当前GC阶段的良好颜色更新全局变量。在退出STW阶段之前,坏位掩码的值从该全局变量加载到该特定寄存器。可以使用用于维护坏位掩码800的附加和/或替代方法。
参考图8A,当前GC阶段是标记开始802。M0可以被选为“良好颜色”。坏位掩码800被设置为“060000”(十六进制,对于M1和R位(坏颜色)为“1”,对于所有剩余位为“0”)。坏位掩码800用在加载屏障中以检查引用是否是为良好颜色。当对坏位掩码800和良好颜色的堆引用应用逻辑按位AND运算(logical bit-wise AND operation)时,结果将全为0。相反,当对坏位掩码800和坏颜色的堆引用应用逻辑按位AND运算时,结果不会全为0。
在标记开始802期间,一个或多个GC线程识别所有根引用820。根引用包括一个或多个调用堆栈上的局部变量中的引用822,以及可从调用堆栈访问的代码高速缓存上的已编译方法中的引用824。如图所示,基于根引用820,对象834f和834g被标记为存活(如由虚线图案所指示的)。
参考图8B,当前GC阶段是标记/重新映射804。坏位掩码800继续是“060000”。GC线程执行对象图遍历以识别和标记所有存活对象。如果发现陈旧引用,那么基于转发表重新映射陈旧引用的地址(下面参考图8D进一步讨论)。下面参考图13进一步描述在标记/重新映射804期间执行的操作的示例。
如图所示,通过对象834g追踪导向对象834a。通过对象834f追踪导向对象834c。因此,对象834a和834c被标记为存活(如由虚线图案所指示的)。因此,堆830中的存活对象包括对象834a、834c、834f和834g。堆830中不使用的对象包括对象834b、834d和834e。
记录每个区段的存活度信息。区段832a有一个存活对象;区段832b有两个存活对象;区段832c有一个存活对象。
未示出地,GC阶段标记停止806和清除选择808被执行。在标记停止806期间,GC线程确认标记已完成。在清除选择808期间,GC线程选择一个或多个区段以供清除。GC线程可以选择要清除的区段832a和832c,因为最大数量的存活对象驻留在区段832b中。附加地或替代地,GC线程可以选择要清除的区段832a和832c,因为区段832a和832c中的每个区段中的存活对象的数量低于阈值。
参考图8C,当前GC阶段是重新定位开始810。坏位掩码800被更新为“030000”(十六进制)。当对坏位掩码800和设置了重新映射位(即,良好颜色)的堆引用应用逻辑按位AND运算时,结果将全为0。相反,当对坏位掩码800和设置了任一标记位(即,坏颜色)的堆引用应用逻辑按位AND运算时,结果不会全为0。
在重新定位开始810期间,GC线程重新定位存储在清除区域中的由根引用820指向的所有对象。根引用820指向的对象包括对象834f和834g。对象834f驻留在清除区域中,因此对象834f从区段832c重新定位到区段832b。对象834g已经驻留在非清除区域,因此对象834g不会被重新定位。
在重新定位开始810期间,GC线程还重新映射根引用。由于对象834f被重新定位,所以指向对象834f的根引用被重新映射为指向对象834f在区段832b内的新位置。在实施例中,转发表(未示出)记录从对象834f在区段832c内的旧地址到对象834f在区段832b内的新地址的映射。
参考图8D,当前GC阶段是重新定位812。坏位掩码800继续为“030000”。GC线程重新定位存储在清除区域中的剩余存活对象,即,对象834a。转发表840记录从对象834a在区段832a内的旧地址到对象834a在区段832b内的新地址的映射。该转发表840随后在指向对象834a的任何引用的懒惰重新映射期间被使用。在实施例中,相同的转发表被用于存储经重新定位的对象的旧地址到新地址的所有映射。在另一个实施例中,可以使用不同的转发表(例如,不同的转发表可以被用于每个清除页面)。
图9图示了根据实施例的多个垃圾收集周期和对应的良好垃圾收集状态(或“良好颜色”)。良好颜色在每个GC周期中改变两次,并且每次选择良好颜色的窗口如图9中所示。
GC周期n包括标记开始902a、标记/重新映射904a、标记结束906a、清除选择908a、重新定位开始910a和重新定位912a。GC周期n+1包括标记开始902b、标记/重新映射904b、标记结束906b、清除选择908b、重新定位开始910b和重新定位912b。标记开始902a、标记/重新映射904a、标记结束906a和清除选择908a的良好颜色可以是M0。因此,“M0窗口”包括标记开始902a、标记/重新映射904a、标记结束906a、清除选择908a。然后,重新定位开始910a、重新定位912a以及GC周期n和GC周期n+1之间的良好颜色是R。因此,“R窗口”包括重新定位开始910a、重新定位912a以及GC周期n和GC周期n+1之间的时间。对于下一个GC周期,标记开始902b、标记/重新映射904b、标记结束906b和清除选择908b的良好颜色变为M1。因此,“M1窗口”包括标记开始902b、标记/重新映射904b、标记结束906b、清除选择908b。随后是针对重新定位开始910b和重新定位912b对“R窗口”(未示出)。
在实施例中,特定一组的颜色被称为“互斥的”,其中在任何给定时间该特定一组颜色中只有一个是“良好”的。该特定一组颜色的其余颜色不为良好。如图所示,例如,特定一组颜色包括M0、M1和R。在给定时间,M0、M1和R中只有一个是“良好”。因此,M0、M1和R可以被称为互斥的一组颜色。
附加地或替代地,特定一组颜色被称为“互斥的”,其中在任何给定时间该特定一组颜色中只有一个颜色与堆引用相关联。该特定一组颜色中的其余颜色不与堆引用相关联。例如,特定一组颜色包括M0、M1和R。在给定时间,M0、M1和R中有且只有一个与特定堆引用相关联。因此,M0、M1和R可以被称为互斥的一组颜色。
在实施例中,堆引用与互斥的一组颜色中的一个且仅一个颜色相关联,而可解除引用的引用不包括该组互斥颜色中的任何颜色的任何指示。然而,可解除引用的引用可以包括其它GC状态的指示,这些状态不在互斥的集合内。返回参考图6,例如,堆引用600的位612、614、616指示M0、M1和R中的哪一个与堆引用600相关联。同时,可解除引用的引用601不包括颜色M0、M1和R中的任何颜色的任何指示。然而,堆引用600可以附加地包括除了M0、M1和R之外的GC状态的指示。堆引用600的其它位618可以指示例如引用的年龄。这种信息维护在可解除引用的引用601的其它位618中。因此,可解除引用的引用601可以包括不在该组互斥的GC状态内的GC状态的指示。
4.加载和写入屏障
在一个或多个实施例中,GC周期包括一个或多个并发的阶段。在并发阶段期间,一个或多个应用线程可以与一个或多个GC线程并发地执行。当应用线程尝试将引用从堆加载到调用堆栈时,应用线程可以执行引用加载屏障。当应用线程尝试将引用写入到堆上时,应用线程可以执行引用写入屏障。当应用线程尝试从代码高速缓存中加载已编译方法时,应用线程可以执行已编译方法加载屏障。
图10图示了根据实施例的引用加载屏障。如图所示,堆1030包括地址000012、000013、......000042、000043、000044。调用堆栈局部变量1032包括寄存器r1、r2、r3。在示例中,引用包括24位。堆引用的颜色可以由第17-19位指示。当颜色为M0时,第17-20位的十六进制值为“1”(或二进制“0001”)。当颜色为M1时,第17-20位的十六进制值为“2”(或二进制“0010”)。当颜色为重新映射时,第17-20位的十六进制值为“4”(或二进制“0100”)。
样本代码可以包括以下内容:
基于代码行Person temp1=new Person(),应用线程在堆1030中创建新对象,并且引用temp1引用该新对象。(由temp1引用的)该对象属于Person类型,并包含String类型的name字段。(由temp1引用的)该对象被存储在堆1030内的地址“000012”处。(由temp1引用的)该对象的name字段被存储在堆1030内的地址“000013”处。name字段用引用1005填充。引用1005包括颜色1006并指向地址“0042”。因此,地址“000042”包含(由temp1引用的)对象的name的值,并且该值为“TOM”。
基于代码行String temp2=temp1.name,应用线程尝试加载temp1引用的对象的name字段中引用1005。此时,引用1005的颜色1006例如可以是M1,其由值“4”(十六进制)表示。
应用线程命中引用加载屏障1010。引用加载屏障1010包括用于检查引用1005是否为良好颜色的指令。逻辑按位AND运算被应用于引用1005和坏位掩码。如果返回值为0,那么引用1005为良好颜色。否则,如果返回值不为0,那么引用1005不为良好颜色。
如果引用1005为良好颜色,那么应用线程采用快速路径1012。快速路径1012不必然涉及任何GC操作(诸如重新映射引用和/或将对象标记为存活)。应用线程从引用1005中移除颜色1006以存储在调用堆栈局部变量1032中。应用线程可以通过使用颜色移除掩码来移除颜色1006。颜色移除掩码可以包括用于指示颜色的每个位(M0、M1和R位)的“0”,以及用于每个剩余位的“1”。在示例中,第17-19位分别对应于M0、M1和R。因此,颜色移除掩码包括用于第17-19位的“0”,以及用于每个剩余位的“1”。颜色移除掩码可以写为F8FFFF(十六进制)。对颜色移除掩码和引用1005应用逻辑按位AND运算。相应地,第17-19位变为“0”,而引用1005的剩余位保持不变。结果“000042”作为引用1007被保存在调用堆栈局部变量1032中,诸如在r3处。应用线程然后可以对引用1007解除引用。应用线程访问由引用1007指示的地址,即堆1030内的地址“000042”。应用线程获得堆1030内的地址“000042”处的值“TOM”。
在实施例中,在对引用1007解除引用之前,应用线程可以首先检查引用1007是否符合规范形式。规范形式可能要求某些位(包括第17-19位)是存储在第1-16位处的值的符号扩展。由于颜色已从引用1007的第17-19位中移除,因此引用1007确实符合规范形式。因而,应用线程可以对引用1007解除引用。
如果引用1005不为良好颜色,那么应用线程采用慢速路径1014。应用线程可以基于由引用1005指示的当前颜色1006来从慢速路径池中选择一个慢速路径。例如,应用线程可以重新映射由引用1005指示的地址。例如,应用可以将引用1005指向的对象标记为存活。然后应用线程将引用1005的颜色1006更新为良好颜色。此外,应用线程从引用1005中移除颜色1006,以供存储在调用堆栈局部变量1032中,如上所述。
图11图示了根据实施例的引用写入屏障。如图所示,堆1130包括地址000012、000013、......000016、000017、...000042、000043、000044。调用堆栈局部变量1132包括寄存器r1、r2、r3。在示例中,引用包括24位。堆引用的颜色可以由第17-19位指示。在颜色为M0的情况下,第17-20位的十六进制值为1(或二进制0001)。在颜色为M1的情况下,第17-20位的十六进制值为2(或二进制0010)。在颜色为R的情况下,第17-20位的十六进制值为4(或二进制0100)。
样本代码可以包括以下内容:
/>
基于代码行Person temp2=new Person(),应用线程在堆1130中创建新对象,并且引用temp2引用该新对象。(由temp2引用的)该对象属于Person类型,并包含String类型的name字段。(由temp2引用的)该对象被存储在堆1130内的地址“000016”处。(由temp2引用的)该对象的name字段被存储在堆1130内的地址“000017”处。name字段用引用1105填充。
基于代码行temp2.name=temp3,应用线程尝试将引用1107从调用堆栈局部变量1132写入到堆1130中。具体地,应用线程尝试将引用1107写入到地址“000017”,该地址是存储temp2所引用的对象的name字段的位置。
在实施例中,存储在调用堆栈局部变量1132上的引用1107符合规范形式。规范形式可能要求某些位(包括第17-19位)是存储在第1-16位处的值的符号扩展。因此,引用1007的第17-19位不指示任何GC状态。
应用线程命中引用写入屏障1110。引用写入屏障1110包括用于将颜色1106添加到引用1107的指令。具体地,应用线程基于坏位掩码和/或当前的GC阶段来确定哪种颜色是当前的良好颜色。然后,应用线程使用该良好颜色为引用1107着色。用良好颜色给引用1107着色可以包括:(a)对坏位掩码和如下值应用逻辑按位XOR(互斥OR)运算,该值包括用于与颜色对应的每个位的“1”以及用于所有剩余位的“0”,以及(b)对XOR的结果和引用1107(“000042”)应用逻辑按位AND。例如,坏位掩码可能是“050000”。对坏位掩码“050000”和值“070000”应用XOR运算。该XOR的结果是“020000”。OR运算被应用于结果“020000”和引用“000042”。该OR的结果是“020042”。应用线程将结果“020042”写入到堆1130中的地址“000017”。
图12图示了根据实施例的已编译方法加载屏障。如图所示,代码高速缓存1230包括地址000072、000073。已编译方法Md1被存储在代码高速缓存1230中。Md1元数据从地址000072处开始存储。Md1代码从地址000073处开始存储。
Md1元数据包括如下字段,该字段具有与引用相同数量(或更少)的位。元数据字段包括与已编译方法Md1相关联的颜色1206的指示。具体地,元数据字段的指示颜色1206的位与堆引用的指示堆引用的颜色的位相同。作为示例,引用的总位数可以是24。包括已编译方法的颜色的指示的元数据字段的总位数可以相同,即24。此外,堆引用的第17-19位可以指示堆引用的颜色。类似地,已编译方法的元数据字段的第17-19位可以指示已编译方法的颜色。在颜色为M0的情况下,元数据字段的第17-20位的十六进制值为1(或二进制0001)。在颜色为M1的情况下,第17-20位的十六进制值为2(或二进制0010)。在颜色为R的情况下,第17-20位的十六进制值为4(或二进制0100)。
已编译方法Md1的颜色1206被隐含到嵌入在Md1代码中的引用。在实施例中,嵌入在已编译方法中的引用符合规范形式。规范形式可能要求某些位(包括第17-19位)是存储在位1-16处的值的符号扩展。因此,嵌入在Md1代码中的引用的第17-19位不指示任何颜色。然而,嵌入的引用的颜色被Md1元数据指示为已编译方法Md1的颜色1206。
应用线程尝试加载已编译方法Md1。应用线程命中已编译方法加载屏障1210(本文也称为“方法加载屏障”)。方法加载屏障1210包括用于检查已编译方法Md1是否为良好颜色的指令。逻辑按位AND运算被应用于Md1元数据和坏位掩码。如果返回值为0,那么已编译方法Md1为良好颜色。否则,如果返回值不为0,那么已编译方法Md1不为良好颜色。
如果已编译方法Md1为良好颜色,那么应用线程采取快速路径1212。快速路径1212不必然涉及任何GC操作(诸如重新映射引用和/或将对象标记为存活)。应用线程可以进行到已编译方法Md1的执行1234。
如果已编译方法md1不为良好颜色,那么应用线程采取慢速路径1214。应用线程可以基于Md1元数据指示的当前颜色1206选择一组候选慢速路径中的一个。应用线程针对嵌入在Md1代码中的每个引用而迭代一组GC操作。例如,应用线程可以重新映射由嵌入的引用指示的地址。例如,应用可以将嵌入的引用所指向的对象标记为存活。然后应用线程将已编译方法Md1的颜色1206更新为良好颜色。然后应用线程可以进行到已编译方法Md1的执行1234。执行1234使用可能(作为慢速路径1214的一部分)已被重新映射的引用。
已编译方法Md1的执行1234包括对嵌入在Md1代码中的引用解除引用。嵌入的引用不必然包括任何颜色指示。
5.通过垃圾收集线程标记堆引用
图13图示了根据实施例的用于由垃圾收集线程标记堆引用的一组操作。图13中所示的一个或多个操作可以一起被修改、重新布置或省略。因此,图13中所示的特定操作顺序不应被解释为限制一个或多个实施例的范围。如图13中所示的操作不限制操作在一组代码中的表达方式。图13的多个操作可以对应于一组代码中的单个指令;相反,图13的单个操作可以对应于一组代码中的多个指令。图13的操作被描述为由单个GC线程执行;然而,这些操作可以由并行执行的多个GC线程执行。
一个或多个实施例包括由GC线程识别来自堆存储器的引用(操作1302)。在GC周期的标记阶段(诸如图7的标记/重新映射704)期间,GC线程识别来自堆存储器的引用。该引用可以作为对对象图的遍历的一部分而被识别。
一个或多个实施例包括确定该引用的当前GC状态是否为“良好”(即,当前标记状态)(操作1304)。由于标记只在M0或M1窗口执行,因此良好的GC状态要么是M0要么是M1,并且不能是重新映射。如果良好的GC状态是M0,那么M0被称为“当前标记状态”,并且M1是“旧标记状态”。如果良好的GC状态是M1,那么M1被称为“当前标记状态”,并且M0是“旧标记状态”。
由于引用的当前GC状态由该引用指示,因此GC线程分析引用本身以确定当前GC状态是否为良好。在示例中,使用坏位掩码。坏位掩码仅在与坏颜色对应的位位置中具有1,并且在所有剩余位中为0。GC线程对引用和坏位掩码应用逻辑按位AND运算。如果结果为0,那么引用的当前GC状态为良好。如果结果不为0,那么引用的当前GC状态不为良好。可以使用其它方法来检查引用的当前GC状态。
如果当前GC状态为良好,那么一个或多个实施例包括识别存储在堆存储器中的要处理的下一个引用(操作1314)。GC线程采用“快速路径”,其涉及跳过GC操作(诸如重新映射引用、将对象标记为存活,和/或更新引用的GC状态(例如,操作1308-1312))。GC线程直接执行操作1314,这将在下面进一步讨论。
如果引用的当前GC状态不为良好,那么一个或多个实施例包括确定引用的当前GC状态是重新映射状态还是旧标记状态(操作1308)。GC线程分析引用以确定该引用的当前GC状态是重新映射状态还是旧标记状态。GC基于当前GC状态选择一组候选慢速路径中的一个。
如果当前GC状态是旧标记状态,那么一个或多个实施例包括(1)基于转发表而重新映射由引用指示的存储器地址,(2)将对应的对象标记为存活,以及(3)将引用所指示的GC状态更新为良好(操作1308-1312)。旧标记状态指示引用可能是过时的。GC线程检查对应的对象是否在紧接在前的GC周期中的重新定位阶段(例如,图7的重新定位712)期间被重新定位。如果对应的对象没有被重新定位,那么不需要重新映射。如果对应的对象被重新定位了,那么GC线程咨询转发表。基于该转发表,GC线程确定该对应对象的新位置。GC线程更新引用以指向该新位置。
此外,GC线程将引用所指向的对象标记为存活。在示例中,对象的元数据内的一个或多个特定位可以指示对象的存活度。GC线程可以设置这些特定的位来指示对象是存活的。在另一个示例中,一个或多个外部位图被用于指示对象的存活度。在同一GC周期中的即将到来的重新定位阶段(诸如图7的重新定位712)期间,GC线程识别已标记为存活的对象并对其重新定位。GC线程不会重新定位未标记为存活的对象。
此外,GC线程将引用所指示的GC状态更新为良好,即当前标记状态。
如果引用的当前GC状态是重新映射状态,那么一个或多个实施例包括(1)将对应对象标记为存活,以及(2)将引用所指示的GC状态更新为良好(操作1310-1312)。重新映射状态指示该引用不是陈旧的——要么该引用已经被重新映射为指向对应对象的新位置,要么该引用不需要被重新映射,因为对应的对象在先前的重新定位阶段期间没有被重新定位。因此,对该引用进行重新映射的GC操作(例如,操作1308)被跳过。
GC线程将引用所指向的对象标记为存活。此外,GC线程将引用所指示的GC状态更新为良好,即当前标记状态。
一个或多个实施例包括由GC线程识别存储在堆存储器中的要处理的下一个引用(操作1314)。GC线程确定是否存在要处理的任何其它引用。如果是,那么GC线程针对下一个引用迭代操作1302-1312。如果没有要处理的其它引用,那么标记结束(例如,GC处理从图7的标记/重新映射704移动到标记结束706)。
6.通过应用线程加载堆引用
图14图示了根据实施例的用于通过应用线程加载堆引用的一组操作。图14中所示的一个或多个操作可以一起被修改、重新布置或省略。因此,图14中所示的特定操作顺序不应被解释为限制一个或多个实施例的范围。如图14中所示的操作不限制操作在一组代码中的表达方式。图14的多个操作可以对应于一组代码中的单个指令;相反,图14的单个操作可以对应于一组代码中的多个指令。图14的操作被描述为由单个应用线程执行;然而,这些操作可以由多个应用线程和/或GC线程执行。
一个或多个实施例包括由应用线程接收用于将引用从堆存储器加载到应用线程的调用堆栈上的请求(操作1402)。在GC系统的并发阶段(例如,图7的标记/重新映射704、清除选择708或重新定位712)期间,应用线程执行一组代码(例如,字节码)。该组代码包括用于将引用从堆存储器加载到应用线程的调用堆栈上的请求。
一个或多个实施例包括由应用线程识别来自堆存储器的引用(操作1404)。应用线程从堆存储器中识别引用(在本文中称为“堆引用”)。
一个或多个实施例包括确定堆引用的当前GC状态是否为“良好”。(操作1406)。应用线程不是直接将该引用存储到调用堆栈上,而是首先命中加载屏障。应用线程检查堆引用的当前GC状态是否为“良好”。应用线程分析堆引用以确定堆引用的当前GC状态是否为良好。上面参考图13的操作1304描述了用于确定堆引用的当前GC状态是否为良好的操作示例。
在实施例中,堆引用不被直接地解除引用。因此,堆引用不必然符合任何解除引用的先决条件(诸如符合规范形式)。因此,堆引用中包含的当前GC状态的指示不必然符合规范形式。当前GC状态的指示可能被存储在例如堆引用的不可寻址部分中。
如果当前GC状态为良好,那么一个或多个实施例包括将不具有任何GC状态的任何指示的引用存储到调用堆栈上(操作1410)。应用线程采用“快速路径”,其中涉及跳过GC操作(诸如重新映射引用、将对象标记为存活和/或更新引用的GC状态(例如,图15中所示的GC操作))。应用线程直接执行操作1410,这将在下面进一步讨论。
如果当前GC状态不为良好,那么一个或多个实施例包括完成一组GC操作以将堆引用从当前GC状态带入良好GC状态(操作1408)。应用线程基于良好的GC状态和堆引用的当前GC状态来选择一组候选慢速路径中的一个。
参考图15,图15图示了根据实施例的用于将堆引用从当前垃圾收集状态带入良好垃圾收集状态的一组路径。表1500指示当前GC状态和良好GC状态的矩阵。
如果良好的GC状态是当前标记状态(M0或M1),并且堆引用的当前GC状态是当前标记状态,那么没有要执行的GC操作。所采用的路径被称为“快速路径”。
与其中良好的GC状态是当前标记状态并且引用的当前GC状态是当前标记状态的图13相比,(a)将引用从堆存储器加载到调用堆栈的应用线程,以及(b)标记堆存储器中引用的GC线程两者都采用快速路径。快速路径不必然涉及任何引用重新映射、对象标记和/或GC状态更新。
如果良好的GC状态是当前标记状态(M0或M1),而堆引用的当前GC状态是重新映射状态,那么要执行的操作包括:(1)将对应的对象标记为存活,以及(2)将堆引用所指示的GC状态更新为良好(即,当前标记状态)。
与其中良好的GC状态是当前标记状态(M0或M1)并且堆引用的当前GC状态是重新映射状态的图13相比,(a)将引用从堆存储器加载到调用堆栈的应用线程,以及(b)标记堆存储器中引用的GC线程两者都采用类似的慢速路径(参见图13的操作1310-1312)。
如果良好的GC状态是当前标记状态(M0或M1),而引用的当前GC状态是旧标记状态,那么要执行的操作包括:(1)如果需要的话,将引用重新映射到新地址,(2)将对应的对象标记为存活,以及(3)将堆引用所指示的GC状态更新为良好(即,当前标记状态)。
与其中良好的GC状态是当前标记状态(M0或M1)并且引用的当前GC状态是旧标记状态的图13相比,(a)将引用从堆存储器加载到调用堆栈的应用线程,以及(b)标记堆存储器中引用的GC线程两者都采用类似的慢速路径(参见图13的操作1308-1312)。
如果良好的GC状态是重新映射状态,并且引用的当前GC状态是当前标记状态,那么要执行的操作包括:(1)如果需要的话,将引用重新映射到新地址,以及(2)将堆引用所指示的GC状态更新为良好(即,重新映射状态)。
如果良好的GC状态是重新映射状态,并且引用的当前GC状态是重新映射状态,那么没有要执行的GC操作。所采用的路径被称为“快速路径”。
一个或多个实施例包括由应用线程将没有任何GC状态的任何指示的引用存储到调用堆栈上(操作1410)。应用线程从堆引用中移除任何GC状态的指示。在示例中,使用了颜色移除掩码。颜色移除掩码对于指示颜色的每个位(例如,M0、M1和R位)具有“0”,并且对于每个剩余位具有“1”。移除任何GC状态的任何指示可以包括对堆引用和颜色移除掩码应用逻辑按位AND运算。应用线程将该AND运算的结果存储到调用堆栈。同时,带有GC状态的指示的堆引用继续被存储在堆存储器中。
在一些实施例中,存储在调用堆栈上的引用不具有GC状态的指示。调用堆栈上的该引用不包括关于相对于该引用的GC操作的进度的任何信息。具体地,堆引用包括(a)指示对应对象的地址的第一组位,以及(b)指示一个或多个GC状态的第二组位。存储在调用堆栈上的引用包括(a)指示同一对应对象的同一地址的相同的第一组位,以及(b)相同的第二组位,但第二组位不指示任何GC状态。
在其它实施例中,存储在调用堆栈上的引用不具有指示互斥的一组GC状态(例如,M0、M1和R)中的哪一个状态与该引用相关联的指示。然而,调用堆栈上的该引用可以指示其它GC状态(例如,引用的年龄)。具体地,堆引用包括(a)指示对应对象的地址的第一组位,(b)指示一组互斥GC状态中与堆引用相关联的一个GC状态的第二组位,以及(c)指示一个或多个其它GC状态的第三组位。存储在调用堆栈上的引用包括(a)指示同一对应对象的同一地址的相同的第一组位,(b)相同的第二组位,但第二组位不指示该组互斥GC状态中与该引用相关联的任何状态,以及(c)指示相同的其它GC状态的相同的第三组位。
在实施例中,应用线程尝试对基于操作1410而存储在调用堆栈上的引用解除引用。如上所述,在一些实施例中,应用线程在其上执行的硬件系统(诸如处理器)要求引用的不可寻址部分在被解除引用之前符合规范形式。因此,在解除引用之前(如果执行解除引用),处理器会验证该引用是否符合规范形式。即使堆引用中包含的GC状态的指示违反了规范形式,该指示也已从调用堆栈上的引用中被移除。因此,处理器确定调用堆栈上的引用符合规范形式。应用线程因此成功对调用堆栈上的引用解除引用。
7.通过应用线程写入堆引用
图16图示了根据实施例的用于通过应用线程写入堆引用的一组操作。图16中所示的一个或多个操作可以一起被修改、重新布置或省略。因此,图16中所示的特定操作顺序不应被解释为限制一个或多个实施例的范围。如图16中所示的操作不限制操作在一组代码中的表达方式。图16的多个操作可以对应于一组代码中的单个指令;相反,图16的单个操作可以对应于一组代码中的多个指令。图16的操作被描述为由单个应用线程执行;然而,这些操作可以由多个应用线程和/或GC线程执行。
一个或多个实施例包括由应用线程接收用于将引用写入到堆存储器上的请求(操作1602)。应用线程执行一组代码(例如,字节码)。该组代码包括用于将引用写入到堆存储器上的请求。例如,该请求可以是将存储在应用线程的调用堆栈上的引用写入到堆存储器上。
在实施例中,该引用不具有关于哪个GC状态是该引用的当前GC状态的任何指示。该引用不包括指示相对于该引用的GC操作的进度的任何信息或元数据。在另一个实施例中,该引用不具有一组互斥的GC状态(例如,M0、M1和R)中的哪一个是该引用的当前GC状态的任何指示;然而,该引用可以包括关于其它GC状态的信息(例如,引用的年龄)。
在实施例中,要写入的引用可能先前已被解除引用(由当前尝试将该引用写入到堆存储器和/或另一个线程的应用线程解除引用)。如上所述,在一些实施例中,应用线程在其上执行的硬件系统(诸如处理器)要求引用的不可寻址部分在被解除引用之前符合规范形式。因此,在解除引用之前(如果先前执行了解除引用的话),处理器会验证引用是否符合规范形式。为了通过验证,该引用不能在不可寻址部分包含任何GC状态指示。在一些情况下,引用在不可寻址部分缺少GC状态的指示,因为GC状态的指示已基于图14的操作被移除了。
一个或多个实施例包括确定与GC处理相关联的“良好”GC状态(操作1604)。应用线程确定与GC处理相关联的“良好”GC状态。在实施例中,应用线程获得当前坏位掩码。应用线程对坏位掩码和如下值应用逻辑按位XOR运算,该值对于与颜色对应的每个位包括“1”并且对于所有剩余位包括“0”(例如,十六进制的070000)。该XOR的结果可以被称为“良好位掩码”。良好位掩码在表示良好GC状态的位中包含“1”,并且在剩余位中包含“0”。可以使用用于确定良好GC状态的附加和/或替代操作。
一个或多个实施例包括由应用线程将如下引用存储到堆存储器上(操作1606),该引用具有将良好GC状态作为该引用的当前GC状态的附加指示。应用线程将良好GC状态的指示添加为引用的当前GC状态。应用将包括引用的当前GC状态的指示的引用存储到堆存储器上。在实施例中,应用线程将逻辑按位OR运算应用于良好位掩码和引用。该OR运算的结果是如下引用,该引用具有良好GC状态作为引用的当前GC状态的指示。OR运算的结果被存储在堆存储器上。
在实施例中,存储在堆上的引用不被直接解除引用。因此,堆引用不必然符合任何解除引用的先决条件(诸如符合规范形式)。因此,堆引用可能包含GC状态的指示,即使该指示违反了规范形式。GC状态的指示可以被存储在例如堆引用的不可寻址部分中。
在实施例中,GC状态的指示被用在对堆引用的后续访问中。作为示例,执行标记阶段的GC线程可以识别该堆引用。GC线程可以基于堆引用所指示的GC状态来选择相对于该引用采取的路径。作为另一个示例,应用线程可以加载堆引用。应用线程可能命中加载屏障。在加载屏障内,应用线程可以基于堆引用所指示的GC状态来选择相对于该引用采取的路径(例如,使用图15的操作)。在执行所选择的路径之后,应用线程可以加载堆引用。
8.通过应用线程加载已编译方法
图17图示了根据实施例的用于通过应用线程加载已编译方法的一组操作。图17中所示的一个或多个操作可以一起被修改、重新布置或省略。因此,图17中所示的特定操作顺序不应被解释为限制一个或多个实施例的范围。如图17中所示的操作不限制操作在一组代码中的表达方式。图17的多个操作可以对应于一组代码中的单个指令;相反,图17的单个操作可以对应于一组代码中的多个指令。图17的操作被描述为由单个应用线程执行;然而,这些操作可以由多个应用线程和/或GC线程执行。
一个或多个实施例包括由应用线程接收用于从代码高速缓存加载已编译方法的请求(操作1702)。应用线程执行一组代码(例如,字节码)。该组代码包括对存储在代码高速缓存中的已编译方法的调用。
一个或多个实施例包括确定已编译方法的当前GC状态是否为“良好”(操作1704)。应用线程不是直接加载和/或执行已编译方法,而是命中加载屏障。由于已编译方法的当前GC状态由元数据字段指示,因此GC线程分析已编译方法的元数据字段来确定当前GC状态是否为良好。已编译方法的元数据字段可以存储在代码高速缓存中。此外,已编译方法的元数据字段可以紧接在已编译方法的代码之前存储。
在实施例中,堆引用内指示堆引用的当前GC状态的位是与已编译方法相关联的元数据字段内指示已编译方法的当前GC状态的位相同的位。因此,用于确定堆引用的当前GC状态是否为良好的操作可以被应用于确定已编译方法的当前GC状态是否为良好。
在示例中,如上所述,坏位掩码可以被用于确定引用是否具有良好的GC状态。对坏位掩码和良好GC状态的堆引用应用逻辑按位AND运算将导致全0。对坏位掩码和不是良好GC状态的堆引用应用逻辑按位AND运算不会导致全0。类似地,应用线程可以对坏位掩码和与已编译方法相关联的元数据字段应用逻辑按位AND运算。如果结果为全0,那么已编译方法的当前GC状态为良好。如果结果不是全0,那么已编译方法的当前GC状态不为良好。可以使用其它方法来检查已编译方法的当前GC状态。
如果当前GC状态为良好,那么一个或多个实施例包括加载和/或执行已编译方法(操作1712)。应用线程采用“快速路径”,其涉及跳过GC操作(诸如重新映射引用和/或将对象标记为存活(例如,图18中所示的GC操作))。应用线程直接执行操作1712,这将在下面进一步讨论。
如果当前GC状态不为良好,那么一个或多个实施例包括确定是否有嵌入在已编译方法中的任何未处理的引用(操作1706)。应用线程基于操作1708确定已编译方法中是否有嵌入的还没有被处理的引用。在实施例中,应用线程遍历已编译方法的代码以确定该代码是否包括任何嵌入的引用。在第一迭代中,遍历可以从代码的开头开始。在下一次迭代中,遍历可以从最新近找到和/或最新近处理的嵌入引用的位置开始。如果应用线程找到嵌入的引用,那么应用继续基于操作1708来处理该嵌入的引用。如果应用到达代码末尾而没有找到任何嵌入的引用,那么该代码不包含任何未处理的引用。
一个或多个实施例包括完成一组GC操作以将嵌入的引用从已编译方法的当前GC状态带入良好GC状态(操作1708)。应用线程选择一组候选慢速路径中的一个路径来处理在操作1706处识别出的嵌入的引用。应用线程基于良好GC状态和已编译方法的当前GC状态(其隐含地也是嵌入的引用的当前GC状态)来选择慢速路径。
参考图18,图18图示了根据实施例的用于将嵌入的引用从当前GC状态带入良好GC状态的一组路径。类似于上面图15的表1500,表1800指示当前GC状态和良好GC状态的矩阵。在加载已编译方法的上下文中,表1800的“当前GC状态”是指嵌入的引用的GC状态(如已编译方法的GC状态所隐含的那样),该状态由与已编译方法相关联的元数据字段指示。
如果良好的GC状态是当前标记状态(M0或M1),并且嵌入引用的当前GC状态是当前标记状态,那么没有要执行的GC操作。所采用的路径被称为“快速路径”。
如果良好的GC状态是当前标记状态(M0或M1),并且嵌入引用的当前GC状态是重新映射状态,那么要执行的操作包括:将对应对象标记为存活。
如果良好的GC状态是当前标记状态(M0或M1),并且引用的当前GC状态是旧标记状态,那么要执行的操作包括:(1)如果需要的话,将引用重新映射到新地址,以及(2)将对应的对象标记为存活。
如果良好的GC状态是重新映射状态,并且引用的当前GC状态是当前标记状态,那么要执行的操作包括:如果需要的话,将引用重新映射到新地址。
如果良好的GC状态是重新映射状态,并且引用的当前GC状态是重新映射状态,那么没有要执行的GC操作。所采用的路径被称为“快速路径”。
比较表1500和表1800,矩阵中的各种路径是类似的,不同之处在于表1800不包括用于更新引用的GC状态的任何操作。加载已编译方法时可能采取的一组路径都不涉及更新嵌入的引用的GC状态,因为嵌入的引用不包含任何GC状态的任何指示。
在一些实施例中,加载已编译方法时可能采用的路径不涉及更新嵌入的引用的GC状态以指示一组互斥的GC状态(例如,M0、M1和R)中的一个;但是一个或多个路径可以包括更新嵌入的引用的其它GC状态(例如,引用的年龄)。嵌入的引用不包括该组互斥的GC状态中的任何状态的任何指示;但是嵌入的引用可以包括其它GC状态或与相对于嵌入的引用的GC操作的进度相关的其它信息。
在操作1708处完成该组GC操作之后,应用线程迭代操作1706以确定已编译方法中是否有嵌入的任何未处理的引用。因此,应用线程因此针对嵌入在已编译方法中的每个引用迭代操作1708。表1800内的相同路径针对嵌入在已编译方法中的每个引用被采用,以将每个引用从当前GC状态带入良好的GC状态。
如果已编译方法不包括任何其它未处理的嵌入的引用,那么一个或多个实施例包括将已编译方法的元数据指示的GC状态更新为良好(操作1710)。应用线程将已编译方法的元数据字段指示的GC状态更新为良好。如果良好的GC状态是当前标记状态,那么应用线程将已编译方法的元数据字段指示的GC状态更新为当前标记状态。如果良好的GC状态是重新映射状态,那么应用线程将已编译方法的元数据字段指示的GC状态更新为重新映射状态。
一个或多个实施例包括加载和/或执行已编译方法(操作1712)。应用线程加载已编译方法。附加地或替代地,应用线程执行已编译方法。执行已编译方法可以包括对嵌入在已编译方法中的引用解除引用。如上所述,在一些实施例中,应用线程在其上执行的硬件系统(诸如处理器)要求引用的不可寻址部分在被解除引用之前符合规范形式。因此,在解除引用之前(如果执行解除引用的话),处理器验证每个嵌入的引用是否符合规范形式。为了通过验证,每个嵌入的引用不能在不可寻址部分中包含任何GC状态指示。然而,嵌入的引用不需要在不可寻址部分中包含任何GC状态指示,因为该GC状态指示被存储在已编译方法的元数据中。因此,处理器确定嵌入的引用符合规范形式。应用线程由此成功地继续以对嵌入的引用解除引用。
9.其它方面;扩展
实施例针对具有包括硬件处理器并且被配置为执行本文所述和/或在以下权利要求中任何一项所述的任何操作的一个或多个设备的系统。
在实施例中,非瞬态计算机可读存储介质包括指令,当所述指令由一个或多个硬件处理器执行时,使得执行本文所述和/或在权利要求中任何一项所述的任何操作。
本文所述的特征和功能的任何组合可以根据一个或多个实施例来使用。在前面的说明书中,各种实施例已经参考许多具体细节进行了描述,这些具体细节可以从一种实现方式到另一种实现方式而不同。因此,说明书和附图应当在说明性而不是限制性的意义上加以考虑。本发明范围的唯一且排他指示,以及申请人预期要作为本发明范围的是由本申请产生的权利要求集合的字面和等效范围,以这种权利要求产生的具体形式,包括任何后续的校正。
10.硬件概述
根据一个实施例,本文所描述的技术由一个或多个专用计算设备来实现。专用计算设备可以是硬连线的以执行技术,或者可以包括诸如被永久性地编程以执行技术的一个或多个专用集成电路(ASIC)、现场可编程门阵列(FPGA)或网络处理单元(NPU)的数字电子设备,或者可以包括编程为根据固件、存储器、其它存储装置或组合中的程序指令执行技术的一个或多个通用硬件处理器。这些专用计算设备还可以将自定义的硬接线逻辑、ASIC、FPGA或NPU与自定义的编程组合来实现技术。专用计算设备可以是台式计算机系统、便携式计算机系统、手持式设备、联网设备或结合硬连线和/或程序逻辑来实现技术的任何其它设备。
例如,图19是示出可以在其上实现本发明的实施例的计算机系统1900的框图。计算机系统1900包括总线1902或用于传送信息的其它通信机制,以及与总线1902耦合用于处理信息的硬件处理器1904。硬件处理器1904可以是例如通用微处理器。
计算机系统1900还包括耦合到总线1902用于存储信息和要由处理器1904执行的指令的主存储器1906,诸如随机存取存储器(RAM)或其它动态存储设备。主存储器1906也可以用于在要由处理器1904执行的指令执行期间存储临时变量或其它中间信息。当这些指令被存储在处理器1904可访问的非暂态存储介质中时,它们使计算机系统1900成为被定制以执行指令中指定的操作的专用机器。
计算机系统1900还包括耦合到总线1902用于存储静态信息和用于处理器1904的指令的只读存储器(ROM)1908或其它静态存储设备。提供了诸如磁盘或光盘的存储设备1910,并且存储设备1910被耦合到总线1902,用于存储信息和指令。
计算机系统1900可以经由总线1902耦合到显示器1912,诸如阴极射线管(CRT),用于向计算机用户显示信息。输入设备1914(其包括字母数字和其它键)被耦合到总线1902,用于将信息和命令选择传送到处理器1904。另一种类型的用户输入设备是光标控件1916,诸如鼠标、轨迹球、或光标方向键,用于向处理器1904传送方向信息和命令选择并且用于控制光标在显示器1912上的移动。这种输入设备通常具有在两个轴(第一轴(例如,x)和第二轴(例如,y))中的两个自由度,这允许设备在平面中指定位置。
计算机系统1900可以使用定制的硬连线逻辑、一个或多个ASIC或FPGA、固件和/或程序逻辑来实现本文描述的技术,这些定制的硬连线逻辑、一个或多个ASIC或FPGA、固件和/或程序逻辑与计算机系统结合使计算机系统1900成为或将计算机系统1900编程为专用机器。根据一个实施例,本文的技术由计算机系统1900响应于处理器1904执行主存储器1906中包含的一条或多条指令的一个或多个序列而执行。这些指令可以从另一个存储介质(诸如存储设备1910)读取到主存储器1906中。包含在主存储器1906中的指令序列的执行使处理器1904执行本文描述的处理步骤。在替代实施例中,可以使用硬连线电路系统代替软件指令或与软件指令组合使用。
如本文所使用的术语“存储介质”是指存储使机器以特定方式操作的数据和/或指令的任何非瞬态介质。这种存储介质可以包括非易失性介质和/或易失性介质。非易失性介质包括例如光盘或磁盘,诸如存储设备1910。易失性介质包括动态存储器,诸如主存储器1906。存储介质的常见形式包括例如软盘、柔性盘、硬盘、固态驱动器、磁带或任何其它磁性数据存储介质、CD-ROM、任何其它光学数据存储介质、具有孔模式的任何物理介质、RAM、PROM和EPROM、FLASH-EPROM、NVRAM、任何其它存储器芯片或盒带。
存储介质与传输介质不同但可以与传输介质结合使用。传输介质参与在存储介质之间传输信息。例如,传输介质包括同轴电缆、铜线和光纤,包括包含总线1902的电线。传输介质还可以采取声波或光波的形式,诸如在无线电波和红外线数据通信期间生成的那些波。
各种形式的介质可以涉及将一条或多条指令的一个或多个序列携带到处理器1904以供执行。例如,指令最初可以被携带在远程计算机的磁盘或固态驱动器上。远程计算机可以将指令加载到其动态存储器中,并且使用调制解调器经电话线发送指令。计算机系统1900本地的调制解调器可以接收电话线上的数据,并且使用红外线发射器将数据转换为红外线信号。红外线探测器可以接收在红外线信号中携带的数据,并且适当的电路系统可以将数据放在总线1902上。总线1902将数据携带到主存储器1906,处理器1904从该主存储器1906检索并执行指令。由主存储器1906接收到的指令可以可选地在被处理器1904执行之前或执行之后存储在存储设备1910上。
计算机系统1900还包括耦合到总线1902的通信接口1918。通信接口1918提供耦合到网络链路1920的双向数据通信,其中网络链路1920连接到本地网络1922。例如,通信接口1918可以是综合业务数字网(ISDN)卡、电缆调制解调器、卫星调制解调器、或向对应类型的电话线提供数据通信连接的调制解调器。作为另一个示例,通信接口1918可以是提供到兼容的局域网(LAN)的数据通信连接的LAN卡。也可以实现无线链路。在任何这种实现中,通信接口1918都发送和接收携带表示各种类型信息的数字数据流的电信号、电磁信号或光信号。
网络链路1920通常通过一个或多个网络向其它数据设备提供数据通信。例如,网络链路1920可以通过本地网络1922提供到主计算机1924或到由互联网服务提供商(ISP)1926操作的数据设备的连接。ISP 1926又通过现在通常称为“互联网”1928的世界范围的分组数据通信网络提供数据通信服务。本地网络1922和互联网1928二者都使用携带数字数据流的电信号、电磁信号或光信号。通过各种网络的信号以及在网络链路1920上并且通过通信接口1918的信号是传输介质的示例形式,其中信息将数字数据携带到计算机系统1900或者携带来自计算机系统1900的数字数据。
计算机系统1900可以通过(一个或多个)网络、网络链路1920和通信接口1918发送消息和接收数据,包括程序代码。在互联网示例中,服务器1930可以通过互联网1928、ISP1926、本地网络1922和通信接口1918传送对应用程序的请求代码。
接收到的代码可以在其被接收到时由处理器1904执行,和/或存储在存储设备1910或其它非易失性存储器中以供以后执行。
在前面的说明书中,已经参考因实现而异的许多具体细节描述了实施例。因此,说明书和附图应当被认为是说明性的而不是限制性的。本发明的范围的唯一且排他的指示以及申请人预期作为本发明的范围的内容是从本申请中发出的权利要求集合的字面和等同范围,以这种权利要求发出的具体形式,包括任何后续的更正。

Claims (34)

1.一种或多种非暂态机器可读介质,所述非暂态机器可读介质存储指令,所述指令在由一个或多个处理器执行时,使得:
由应用线程接收用于将对第一对象的第一引用从堆存储器加载到所述应用线程的调用堆栈上的请求;
从所述堆存储器中检索第一引用,其中第一引用包括(a)第一对象在至少第一时间段期间在所述堆存储器中被存储的第一存储器地址,以及(b)多个垃圾收集状态中与第一引用相关联的第一垃圾收集状态的指示;
其中,所述多个垃圾收集状态中的相应垃圾收集状态指示相对于存储在所述堆存储器中的多个引用中的每个引用的垃圾收集操作的进度;
至少通过从第一引用中移除第一垃圾收集状态的指示来从第一引用生成第二引用;
将第二引用存储到所述调用堆栈上,而没有所述多个垃圾收集状态中的任何垃圾收集状态的任何指示。
2.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
基于与第一引用相关联的第一垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径;
其中,所述多个路径中的至少一个路径包括更新第一引用以指示所述多个垃圾收集状态中的第二垃圾收集状态与第一引用相关联。
3.如权利要求2所述的一种或多种介质,其中,所述多个路径中的至少一个其它路径不包括对第一引用进行任何改变以指示所述多个垃圾收集状态中的不同垃圾收集状态与第一引用相关联。
4.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
更新第一引用以指示所述多个垃圾收集状态中的第二垃圾收集状态与第一引用相关联;
在更新第一引用之后:由所述应用线程接收用于将来自第一对象的第一引用从所述堆存储器加载到所述应用线程的所述调用堆栈上的第二请求;
基于与第一引用相关联的第二垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径。
5.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
更新第一引用以指示所述多个垃圾收集状态中的第二垃圾收集状态与第一引用相关联;
在更新第一引用之后:由垃圾收集线程识别第一引用;
基于与第一引用相关联的第二垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径;
其中,所述多个路径中的至少一个路径包括更新第一引用以指示第一垃圾收集状态与第一引用相关联。
6.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
基于与第一引用相关联的第一垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径;
其中,所述多个路径中的至少一个路径包括重新映射第一引用以用第一对象在至少第二时间段期间在所述堆存储器中被存储的第二存储器地址来替换第一存储器地址。
7.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
基于与第一引用相关联的第一垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径;
其中,所述多个路径中的至少一个路径包括将第一对象标记为存活。
8.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
基于由垃圾收集线程执行的当前垃圾收集周期的当前阶段,确定所述多个垃圾收集状态中的良好垃圾收集状态;
基于所述良好垃圾收集状态和与第一引用相关联的第一垃圾收集状态:从多个路径中选择要相对于第一引用执行的路径;
相对于第一引用执行所选择的路径。
9.如权利要求1所述的一种或多种介质,其中,第二引用包括以下之一:
第一对象在至少第一时间段期间在所述堆存储器中被存储的第一存储器地址;或者
第一对象在至少第二时间段期间在所述堆存储器中被存储的第二存储器地址,而不是第一存储器地址。
10.如权利要求1所述的一种或多种介质,其中,与第一引用相关联的第一垃圾收集状态的指示被存储在第一引用的不可寻址部分中。
11.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
对第二引用解除引用。
12.如权利要求1所述的一种或多种介质,还存储指令,所述指令使得:
在对第二引用解除引用之前:验证第二引用符合规范形式;
其中,包括第一垃圾收集状态的指示的第一引用不符合所述规范形式。
13.如权利要求1所述的一种或多种介质,其中,第一引用内的第一组位包括与第一引用相关联的第一垃圾收集状态的指示,并且第二引用的相同的第一组位包括第二引用的可寻址部分的符号扩展。
14.一种或多种非暂态机器可读介质,所述非暂态机器可读介质存储指令,所述指令在由一个或多个处理器执行时,使得:
由应用线程识别用于将第一引用写入到堆存储器上的请求;
确定多个垃圾收集状态中与由垃圾收集线程执行的垃圾收集周期的当前阶段相关联的第一垃圾收集状态;
其中,第一引用不包括所述多个垃圾收集状态中的任何垃圾收集状态的任何指示;
至少通过添加第一垃圾收集状态的指示而从第一引用生成第二引用;
将第二引用存储到所述堆存储器上。
15.如权利要求14所述的一种或多种介质,其中,第一垃圾收集状态与如下引用相关联,针对所述引用,与所述垃圾收集周期的所述当前阶段相关联的一组垃圾收集操作已完成。
16.如权利要求14所述的一种或多种介质,其中,所述多个垃圾收集状态中的相应垃圾收集状态指示相对于存储在所述堆存储器中的多个引用中的每个引用的垃圾收集操作的进度。
17.如权利要求14所述的一种或多种介质,其中,要写入到所述堆存储器上的第一引用被存储在所述应用线程的调用堆栈上。
18.如权利要求14所述的一种或多种介质,还存储指令,所述指令使得:
由垃圾回收线程识别第二引用;
基于与第一引用相关联的第一垃圾收集状态:从多个路径中选择要相对于第二引用执行的路径;
其中,所述多个路径中的至少一个路径包括更新第一引用以指示所述多个垃圾收集状态中的第二垃圾收集状态与第二引用相关联。
19.如权利要求14所述的一种或多种介质,其中,在由所述垃圾收集线程执行的所述垃圾收集周期的所述当前阶段期间,第一垃圾收集状态是良好垃圾收集状态。
20.如权利要求14所述的一种或多种介质,其中,第一引用符合规范形式,并且第二引用不符合所述规范形式。
21.一种或多种非暂态机器可读介质,所述非暂态机器可读介质存储指令,所述指令在由一个或多个处理器执行时,使得:
识别存储在存储器位置中的已编译方法;
确定与所述已编译方法相关联的元数据指示多个垃圾收集状态中的第一垃圾收集状态与所述已编译方法相关联;
其中,所述多个垃圾收集状态中的相应垃圾收集状态指示相对于存储在堆存储器中的多个引用中的每个引用的垃圾收集器操作的进度;
基于与所述已编译方法相关联的第一垃圾收集状态:从多个路径中选择要相对于嵌入在所述已编译方法中的多个引用中的每个引用执行的路径。
22.如权利要求21所述的一种或多种介质,其中,至少所述识别操作和所述确定操作由应用线程或垃圾收集线程之一执行。
23.如权利要求21所述的一种或多种介质,还存储指令,所述指令使得:
相对于所述多个引用中的每个引用执行所选择的路径。
24.如权利要求21所述的一种或多种介质,其中,相对于所述多个引用中的每个引用执行所选择的路径包括:
相对于所述多个引用中的每个引用,完成与所述垃圾收集周期的所述当前阶段相关联的一组垃圾收集操作。
25.如权利要求21所述的一种或多种介质,还存储指令,所述指令使得:
更新与所述已编译方法相关联的所述元数据以指示所述多个垃圾收集状态中的第二垃圾收集状态与所述已编译方法相关联。
26.如权利要求21所述的一种或多种介质,还存储指令,所述指令使得:
加载所述已编译方法和执行所述已编译方法中的至少一个。
27.如权利要求21所述的一种或多种介质,还存储指令,所述指令使得:
更新与所述已编译方法相关联的所述元数据以指示所述多个垃圾收集状态中的第二垃圾收集状态与所述已编译方法相关联;
执行所述已编译方法;
在执行所述已编译方法之后:
基于与所述已编译方法相关联的第二垃圾收集状态:从所述多个路径中选择要相对于嵌入在所述已编译方法中的所述多个引用中的每个引用执行的另一路径。
28.如权利要求21所述的一种或多种介质,其中,嵌入在所述已编译方法中的所述多个引用不指示所述多个垃圾收集状态中与所述多个引用相关联的任何垃圾收集状态。
29.如权利要求21所述的一种或多种介质,其中,所述垃圾收集线程基于所述多个垃圾收集状态中与所述已编译方法相关联的当前垃圾收集状态对嵌入在所述已编译方法中的所述多个引用执行垃圾收集。
30.如权利要求21所述的一种或多种介质,其中,所述应用线程基于所述多个垃圾收集状态中与所述已编译方法相关联的当前垃圾收集状态对嵌入在所述已编译方法中的所述多个引用执行垃圾收集。
31.如权利要求21所述的一种或多种介质,其中,所述已编译方法和与所述已编译方法相关联的所述元数据被存储在代码高速缓存中。
32.一种包括如权利要求1-31中任一项所述的操作的方法。
33.一种包括硬件处理器并被配置为执行如权利要求1-31中任一项所述的操作的系统。
34.一种包括用于执行如权利要求1-31中任一项所述的操作的装置的系统。
CN202180086504.8A 2020-10-29 2021-08-30 跟踪引用的垃圾收集状态 Pending CN116685957A (zh)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US17/084,053 2020-10-29
US17/084,053 US11573894B2 (en) 2020-10-29 2020-10-29 Tracking garbage collection states of references
PCT/US2021/048224 WO2022093381A1 (en) 2020-10-29 2021-08-30 Tracking garbage collection states of references

Publications (1)

Publication Number Publication Date
CN116685957A true CN116685957A (zh) 2023-09-01

Family

ID=78000783

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202180086504.8A Pending CN116685957A (zh) 2020-10-29 2021-08-30 跟踪引用的垃圾收集状态

Country Status (4)

Country Link
US (1) US11573894B2 (zh)
EP (1) EP4237951A1 (zh)
CN (1) CN116685957A (zh)
WO (1) WO2022093381A1 (zh)

Families Citing this family (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US11875193B2 (en) 2021-03-25 2024-01-16 Oracle International Corporation Tracking frame states of call stack frames including colorless roots
US11573794B2 (en) 2021-03-25 2023-02-07 Oracle International Corporation Implementing state-based frame barriers to process colorless roots during concurrent execution
US11513954B2 (en) * 2021-03-25 2022-11-29 Oracle International Corporation Consolidated and concurrent remapping and identification for colorless roots
US11507503B1 (en) 2021-05-19 2022-11-22 Oracle International Corporation Write barrier for remembered set maintenance in generational Z garbage collector
US20240126688A1 (en) * 2022-10-17 2024-04-18 Oracle International Corporation Lazy compaction in garbage collection

Family Cites Families (30)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CA2030404A1 (en) 1989-11-27 1991-05-28 Robert W. Horst Microinstruction sequencer
US5928357A (en) 1994-09-15 1999-07-27 Intel Corporation Circuitry and method for performing branching without pipeline delay
US5842016A (en) * 1997-05-29 1998-11-24 Microsoft Corporation Thread synchronization in a garbage-collected system using execution barriers
US5873104A (en) 1997-06-26 1999-02-16 Sun Microsystems, Inc. Bounded-pause time garbage collection system and method including write barrier associated with source and target instances of a partially relocated object
GB9717715D0 (en) 1997-08-22 1997-10-29 Philips Electronics Nv Data processor with localised memory reclamation
JP4265610B2 (ja) * 1997-11-21 2009-05-20 オムロン株式会社 プログラム制御装置、プログラム制御方法、およびプログラム記録媒体
GB9825102D0 (en) 1998-11-16 1999-01-13 Insignia Solutions Plc Computer system
US6769004B2 (en) 2000-04-27 2004-07-27 Irobot Corporation Method and system for incremental stack scanning
US7225439B2 (en) 2003-03-21 2007-05-29 Sun Microsystems, Inc. Combining write-barriers within an inner loop with fixed step
US20040186863A1 (en) 2003-03-21 2004-09-23 Garthwaite Alexander T. Elision of write barriers for stores whose values are in close proximity
US7089272B1 (en) 2003-06-18 2006-08-08 Sun Microsystems, Inc. Specializing write-barriers for objects in a garbage collected heap
US7404182B1 (en) * 2003-10-03 2008-07-22 Sun Microsystems, Inc. Deferring and combining write barriers for a garbage-collected heap
US7546587B2 (en) 2004-03-01 2009-06-09 Microsoft Corporation Run-time call stack verification
US7512930B2 (en) 2004-03-31 2009-03-31 Intel Corporation Program object read barrier
US7962707B2 (en) * 2005-07-06 2011-06-14 Honeywell International Inc. Apparatus and method for deterministic garbage collection of a heap memory
US20070022149A1 (en) * 2005-07-22 2007-01-25 International Business Machines Corporation System and method for concurrent garbage collection
US9208081B1 (en) * 2007-11-30 2015-12-08 Oracle America, Inc. Concurrent object management
US8825719B2 (en) * 2008-10-30 2014-09-02 Microsoft Corporation Incremental lock-free stack scanning for garbage collection
US8489653B2 (en) * 2011-02-08 2013-07-16 International Business Machines Corporation Incremental class unloading in a region-based garbage collector
US9495395B2 (en) 2013-04-11 2016-11-15 Oracle International Corporation Predictive diagnosis of SLA violations in cloud services by seasonal trending and forecasting with thread intensity analytics
US9355029B2 (en) * 2013-06-28 2016-05-31 Sap Se Thread-based memory management with garbage collection
US9767019B2 (en) 2013-09-17 2017-09-19 Red Hat, Inc. Pauseless garbage collector write barrier
US10503429B2 (en) * 2016-03-31 2019-12-10 EMC IP Holding Company LLC System and method for reference tracking garbage collector
US9846645B1 (en) * 2016-05-27 2017-12-19 Hewlett Packard Enterprise Development Lp Managing objects stored in memory
US10261898B1 (en) * 2016-10-06 2019-04-16 Google Llc Concurrent marking of location and shape changing objects
US10565104B2 (en) * 2017-08-01 2020-02-18 International Business Machines Corporation System and method to manage and share managed runtime memory for JAVA virtual machine
US11442795B2 (en) 2018-09-11 2022-09-13 Nvidia Corp. Convergence among concurrently executing threads
US10922081B2 (en) 2018-10-19 2021-02-16 Oracle International Corporation Conditional branch frame barrier
US11132294B2 (en) 2019-03-28 2021-09-28 International Business Machines Corporation Real-time replicating garbage collection
KR20210111527A (ko) * 2020-03-03 2021-09-13 에스케이하이닉스 주식회사 메모리 시스템에서 가비지 컬렉션을 수행하는 장치 및 방법

Also Published As

Publication number Publication date
WO2022093381A1 (en) 2022-05-05
US20220138098A1 (en) 2022-05-05
EP4237951A1 (en) 2023-09-06
US11573894B2 (en) 2023-02-07

Similar Documents

Publication Publication Date Title
US11573894B2 (en) Tracking garbage collection states of references
US11249758B2 (en) Conditional branch frame barrier
US11474832B2 (en) Intelligently determining a virtual machine configuration during runtime based on garbage collection characteristics
US10733095B2 (en) Performing garbage collection on an object array using array chunk references
CN117581214A (zh) 用于分代z垃圾收集器中的记忆集维护的写屏障
US11573794B2 (en) Implementing state-based frame barriers to process colorless roots during concurrent execution
US11513954B2 (en) Consolidated and concurrent remapping and identification for colorless roots
US11875193B2 (en) Tracking frame states of call stack frames including colorless roots
CN117597671A (zh) Z垃圾收集器中的开始时快照标记
CN117581215A (zh) Z垃圾收集器中的无色根实现
US11789863B2 (en) On-the-fly remembered set data structure adaptation
US20240126688A1 (en) Lazy compaction in garbage collection
WO2022245659A1 (en) Colorless roots implementation in z garbage collector
WO2022245954A1 (en) Write barrier for remembered set maintenance in generational z garbage collector
WO2022245749A1 (en) Snapshot at the beginning marking in z garbage collector

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination