1. 垃圾回收器

职责

  • 分配内存
  • 保证有引用对象不被回收
  • 保证无引用对象被回收

设计方式

串行(Serial)与并行(Parallel)

串行的回收方式, 每次只能执行一种操作. 例如, 在多 cpu 的情况下, 只能有一个 cpu 来执行回收.

而并行则可以将回收任务分为多部分交给不同的 cpu 同时执行.  并行的方式速度更快, 但是会牺牲一些额外的复杂度和造成一些潜在的内存碎片

Concurrent vs Stop-the-world

Stop-the-world 的方式回收垃圾, 会使得程序的执行完全被挂起, 知道回收完成. 而 Concurrent 的方式则可以让垃圾回收任务与程序同时运行.Concurrent 只有小部分情况下会有短暂的 stop-the-world 的行为. Stop-the-world 的垃圾回收则比 Concurrent 更简单, 因为此时堆空间是静止的, 里面的对象不会发生改变. 而 Concurrent 的暂停时间会更短, 但是堆内对象在垃圾回收时还会更新, 所以他会有额外的性能开销, 并且需要更大的堆空间

压缩(Compacting) vs 非压缩(Non-compacting) vs 复制(Copying) 

采用压缩的方式, 在垃圾回收期决定了哪些对象是存活的, 哪些是垃圾以后, 他会将存活都放在一起, 让后回收垃圾对象. 这样在下次分配内存空间的时候会更高效.

而非压缩的方式, 则是将垃圾对象原地释放(并不会移动存活的对象来创造连续的内存空间). 他的优点是回收速度更快, 但是会造成内存碎片, 使得分配内存的代价更大, 因为在分配的时候需要去搜索堆空间找到一块大内存来容纳一个大的对象.

复制回收器则会将存活对象都复制到一块新的空间, 优点是源内存空间可以被视为是空的, 回收更快, 缺点是需要额外的内存空间.

性能指标

  • 吞吐量(Throughput) - 非垃圾回收时间占总时间百分比
  • 垃圾回收开销(Garbage collection overhead) - 与吞吐量相反, 垃圾回收时间占总时间百分比
  • 暂停时间(Pause time) - 垃圾回收期间程序暂停的时间
  • 回收频率(Frequency of collection) - 垃圾回收频率
  • 资源占用(Footprint) - 参数的大小, 例如堆大小
  • 即时性(Promptness) - 对象变为垃圾到这块内存变为可用的时间

对于交互式程序来说, 更重要的是低暂停时间, 而非交互式程序则更关心总的垃圾回收时间.

 

2. J2SE 5.0 HotSpot JVM 的垃圾回收器

HotSpot 的分代机制

HotSpot JVM 中的内存被分为三代: young generation, old generation, permanent generation. 绝大部分对象的初始化都在 young 区. Old 则包含多次年轻代垃圾回收后存活下来的对象, 也包括一些无法分配到 young 中的大对象, 他们会被直接分配到 old. Permanent 则是包括一些 JVM 需要查找的便利信息, 例如对象类方法描述信息.

Young 由 Eden 和两个 Survivor 组成, 如图所示. 绝大部分对象在 Eden 初始化, 部分大对象会直接分配到年老代. Survivor 用来保存在 young 垃圾回收后存活下来的对象. 任何时候, survivor 区都是一个保存了上述的存活对象(标记为 From), 一个是空的, 空的留作下次回收时使用.

垃圾回收类型

每当 young 满了,  会进行一次 young generation collection (又叫 minor collection), 这次回收只针对 young 区. 每当 old 或者 permanent 满了, 会进行一次 full collection (又叫 major collection). 这次回收会对所有代进行回收. 一般来说, young 回收首先发生, 它使用专门对 young 设计的算法, 这个算法对 young 区最高效. 然后会使用 old 区回收算法对 old 和 permanent 进行回收. 而如果有压缩, 则每个代都会分别进行压缩.

有时候 old 区会因为数据太多造成放不下从 survivor 传过来的对象, 这时候, 除了 CMS 回收器以外, 会发生一次使用 old 回收算法对整个堆的回收. (CMS old 区回收算法是特殊情况, 它无法对 young 区进行回收)

快速内存分配

从大块的内存中分配空间效率是非常高的, 因为它使用了 bump-the-pointer 技术. 因为它会使用指针一直追踪最后一次内存分配的对象, 当新的分配发生时, 只需要检查剩余的内存是否足够, 然后移动指针并初始化对象.

对于多线程程序, 分配操作必须保证线程安全, 而使用全局锁则会造成性能瓶颈. HotSpot JVM 使用了一个叫做 Thread-Local Allocation Buffers (TLABs) 的技术. 它通过给每个线程分配自己的线程缓存来提高内存分配效率. 由于他们可以从自己的缓存中分配内存, 所以不需要全局锁, 配合 bump-the-pointer 技术则可以很快的分配内存. 只有在 TLAB 满了的时候, 需要申请更多的空间的时候才需要全局锁.

Serial Collector

使用串行回收器, young 和 old 的回收会使用单个 cpu 并用 stop-the-world 的方式串行执行.

1) Young 区使用 Serial Collector

下图是 young 区回收示意图. Eden 中的存活对象会被复制到标记为 To 的 Survivor 区 (除了那些过大的对象, 会被直接复制到 Old 区). 同样, 标记为 From 的 Survivor 区的存活对象也会被复制到 To 区, 而 From 中足够老的对象则会复制到 Old 区.

如果 To 区已经满了, Eden 和 From 中还存活的对象则会直接复制到 Old 区. 在复制完成以后, 那些留在 Eden 和 From 中没有被复制的对象都会被标记为垃圾.

当 young 回收完成后, Eden 和原来的 From 都会被清空, 只有原来的 To 会存在存活的对象. 然后 From 和 To 会相互交换角色 (From 变成 To, To 变成 From). 如图

2) Old 区使用 Serial Collector

Old 区的串行回收使用 mark-sweep-compact 算法. Mark 阶段, 回收器标记所有存活的对象. Sweep 阶段, 回收器扫描所有代, 并识别出哪些是垃圾. 最后回收器会进行滑动压缩 (sliding compaction), 将存活对象都压缩到 old 区的起始端, 将空闲空间留在相反的一端. 这样在下次分配内存的时候就可以使用 bump-the-pointer 技术快速分配了. 如图

3) 何时使用 Serial Collector

串行回收一般用于对暂停时间需求不高的客户端机器. 目前的硬件条件, 大部分64MB堆空间的程序可以再半秒左右的时间完成一次 full collection. (注: 文章写于 2008 年)

4) 启用 Serial Collector

在 J2SE 5.0 版本, 串行回收器在非服务器上默认启用, 也可以通过参数 -XX:+UseSerialGC 启用.

Parallel Collector

1) Young 区使用 Parallel Collector

Young 区并行回收使用与串行回收一样的算法的并行版本, 它会 stop-the-world, 不同点在于它使用多 cpu 进行并行收集, 降低了垃圾收集的开销, 增加了程序吞吐量. 如下图所示, stop-the-world 的时间变短了

2) Old 区使用 Parallel Collector

Old 区的并行回收使用与串行回收一样的 mark-sweep-compact 算法.

3) 何时使用 Parallel Collector

Parallel Collector 适合运行在多 cpu 的机器上, 并且容许较长的暂停时间的程序, 这是因为 Old 区无法使用并行收集, 依然会有长时间的GC.

你可能会考虑 parallel compacting collector, 因为相比 Parallel Collector, 它会在所有代使用并行收集, 而不仅仅是 Young 区.

4) 开启 Parallel Collector

在 J2SE 5.0 版本, parallel collector 在服务器上自动被选为默认垃圾回收期. 其他机器上, 可以使用 -XX:+UseParallelGC 手动开启

Parallel Compacting Collector

Parallel Compacting Collector 是在 J2SE 5.0 update 6 引入的. 它跟 Parallel Collector 的区别在于它在 Old 区使用了新的回收算法. 注意: 最终 parallel compacting collector 会替代 parallel collecltor

1) Young 区使用 Parallel Compacting Collector

Young 区的垃圾回收与 Parallel Collector 一样

2) Old 区使用 Parallel Compacting Collector

Parallel Compacting Collector 在 Old 区的实现方式依然是使用并行滑动压缩的 stop-the-world 方式. 收集分为三个阶段.

  a) 首先, 每个代都会被逻分为固定大小的逻辑区域

  b) 标记阶段 (Marking Phase). 程序代码中直接可达的存活对象初始集会在垃圾回收线程间被切分, 然后所有的存活对象会被并行标记. 每当一个对象被标记为存活, 它所在的那个逻辑区域的关于这个存活对象的大小, 位置信息就会被更新

  c) 汇总阶段 (Summary Phase). 由于上一次垃圾回收时的压缩操作, 一般来说 Old 区的左边区域存活对象的密度会较高. 这种密度高的区域中, 可以回收的空间不多, 所以压缩他们的可用空间的代价太高. 所以汇总阶段做的第一件事情就是测试区域密度. 从最左边的那个区域开始, 一直到找到一个点, 压缩这个点的右边的区域是代价是值得的. 这个点左边的区域叫做密度前缀 (Dense Prefix), 这些区域不会有新的对象写入. 这个点右边的区域将被压缩, 并清除所有死亡对象. 汇总阶段计算并存储了每个压缩区域的存活对象的第一个字节的地址. 注意: 汇总阶段目前的是实现是串行执行的, 因为相对来说,  标记和压缩阶段的并行执行更重要

  d) 压缩阶段 (Compacting Phase). 垃圾回收线程使用汇总阶段得出的信息来找出需要压缩的区域, 并且所有线程都能独立的复制数据到这些区域中. 最后 Heap 的一端会变成具有高密度存活对象的空间, 而另一端则变成一大块空闲空间.

3) 何时使用 Parallel Compacting Collector

Parallel Compacting Collector 适合那些使用多CPU, 并且对暂停时间有要求的应用. 但是它不适合那些跑在大型共享机器上的应用集群 (例如 SunRays), 这种应用集群不允许单个引用长时间占用多个 CPU. 在这种集群上, 需要考虑减少垃圾回收的线程数 (使用 -XX=ParallelGCThreads=n), 或者选择其他垃圾收集器

4) 启用 Parallel Compacting Collector

使用参数 -XX:+UseParallelOldGC 启用 

Concurrent Mark-Sweep (CMS) Collector

1)  Young 区使用 CMS

跟 Parallel Collector 在 Young 区是一样的

2) Old 区使用 CMS

CMS 在回收时首先会进入一个称之为 initial mark 的短暂停, 这个阶段会标记代码中直接可达的存活对象. 然后会进入 concurrent marking 阶段, 这个阶段会标记所有简介可达的存活对象. 因为此时程序还在运行, 它会更新引用, 所以并不是所有存活的对象都能保证被标记到. 为了解决这个问题, CMS 会进入另一个短暂停, 称之为 remark, 它会重新去标记在 concurrent marking 阶段被修改的对象. 因为 remark 的暂停时间比 initial mark 更长, 这个阶段会用多线程来提升效率.

在最后的 remark 阶段, 所有堆中的存活对象都会保证被标记, 所以下一个 concurrent sweep 阶段会回收所有被标记的垃圾. 下图显示了 Serial mark-sweep-compact 和 CMS 的区别

CMS 是唯一一个 non-compacting 的收集器. 也就是说它在释放了所有死亡对象的空间以后,  它不会将存活对象移动到 Old 区的一端, 如图

这种方法节省了时间, 但是由于空闲内存空间不是连续的, 所以收集器不能使用一个指针来指向下一块空间内存地址. 它创建了一些 list 将未分配区域的内存连在一起, 每次需要分配内存时, 会根据需要内存的数量来搜索一块足够大的空间内存区域. 所以它在分配内存的时候的开销回避 bump-the-pointer 的方法更大. 同时这也加大了 young 区回收的开销, 因为 young 去在将对象移动到 old 的时候需要在 old 分配内存.

CMS 的另一个缺点是需要更大的堆空间. 因为在 marking 阶段, 它还可以继续分配内存, 这就增大了 Old 区的大小. 另外, 虽然 CMS 保证识别出所有存活对象, 但是在标记过程中存活对象可能会死亡, 这些对象只能等到下一次回收才能被释放. 这种对象称之为 floating garbage.

最后, 由于缺少 compaction, 可能会有碎片 (fragmentation) 存在. 为了解决碎片问题, CMS 计算出占比最多的对象大小, 预测未来的需求, 然后将空间的内存切分或者组合成需要的块.

跟其他垃圾收集器不一样, CMS 不会等到 Old 区满了才进行回收, 而是在 Old 区满之前就进行回收. 否则它就退化成了跟 serial collector 一样耗时的 stop-the-world mark-sweep-compact 算法了. CMS 通过统计过去的回收耗费的时间以及 Old 区满的时间来决定何时开始回收. 另外, CMS 会在 Old 区占用空间超过一个叫 initialting occupancy 的阈值的时候开始回收. 这个值可以通过 -XX:CMSInitiatingOccupancyFraction=n 来设置, n 表示 Old 区大小已使用的百分比, 默认是 68.

总的来说, 跟 parallel collector 相比, CMS 降低了暂停时间, 但是会稍微增加 Young 区回收的暂停时间, 并且需要更大的 heap 空间. 

3) Incrememtal Mode 

CMS 的并行阶段可以增量的运行. 它通过间歇性的暂停回收工作将 CPU 让出来交还给程序. 它把工作时间切分成了回收阶段的小块. 这个模式在那些运行在只有很少的 CPU 核数 (例如 1 或 2 个) 的机器上, 并且需要很短的暂停时间的程序很有用.

4) 何时使用 CMS

当你需要更短的回收暂停时间, 并且允许垃圾回收期共享 CPU 资源的时候, 可以考虑 CMS. 一般来说, Old 区占用量大, 并且程序跑在多核 CPU 机器上倾向于使用 CMS. 典型的例子就是 Web 服务器. 在单核 CPU 机器上, 小 Old 区的程序也可以考虑使用.

5) 启用 CMS

可以通过指定参数 -XX:+UseConcMarkSweepGC 来启用. 如果你想使用 Incremental 模式, 启用参数 -XX:+CMSIncrementalMode. 

3. Ergonomics -- Automatic Selections and Behavior Tuning

在 J2SE 5.0 版本中, 会根据程序运行的操作系统平台来自动选择垃圾回收期, 堆大小, HotSpot 虚拟机 (client 或 server).

另外, 可以加入期望的行为目标参数, 来对垃圾收集器进行动态调整, 根据平台来默认选择参数和垃圾收集器动态调试组合成了 ergonomics. 它的目标是使用最少的命令行来获得最优的 JVM 性能

Automatic Selection of Collector, Heap Sizes, and Virtual Machine 

服务器级机器的定义是:

  • 拥有 2 个或更多处理器
  • 2G 或更多内存

除了 32 位的 Windows 操作系统, 其他平台这个定义均适用

而非服务器级别的机器的默认配置如下:

  • 使用 client JVM
  • 使用 serial garbage collector
  • 初始堆大小 4 MB
  • 最大堆大小是 64 MB

服务器级的机器除了显式指定 -client 参数, 总是会使用 server JVM

服务器级的机器无论是跑的 server JVM 还是 client JVM, 它的堆大小都如下:

  • 初始堆大小是 1/64 物理内存, 最大 1GB.
  • 最大堆内存是 1/4 物理内存, 最大 1GB

Behavior-based Parallel Collector Tuning

基于行为的并行收集器调试可以设置如下的调试目标

Maximum Pause Time Goal

最大暂停时间目标可以通过

 -XX:MaxGCPauseMillis=n

来进行设置

他的意思是告诉 parallel collector 暂停时间希望小于 n 毫秒. parallel collector 会通过调整堆大小以及其他垃圾回收相关的参数来达成这个目的. 这可能会降低整个程序的 throughput, 某些情况下这个目标也可能无法达成.

最大暂停时间目标在每个 generation 的执行是分开的. 如果说目标没有达成, 则会所见 generation 的大小. 默认没有最大暂停时间上限.

Throughput Goal

吞吐量目标通过垃圾回收时间与程序运行时间比值来衡量. 可以通过命令 

-XX:GCTimeRatio=n

来启用, 这个比值的表达式如下

  1 / (1 + n)

例如 -XX:GCTimeRatio=19 表示垃圾收集时间应该占程序时间的 5%. 默认的目标是 1% ( n = 99 ). 这个垃圾收集时间指的是对所有 generation 的时间总和. 如果目标没有达成, generation 的大小会增加, 以增加程序在每个 generation 回收之前的运行时间 - 因为更大的 generation 则需要更多的时间才能填满.

Footprint Goal

如果上述的两个目标都已经达成, 则垃圾收集器会缩减 heap size, 直到其中一个目标无法达成 ( 总是 throughput goal ).

Goal Priorities

Parallel collector 首先会尝试达成 Maximun Pause Time Goal. 只有当这个目标达成了才会去处理 Throughput Goal. 类似的, 只有当前面两个目标达成才会处理 Footprint Goal.

4. Tools to Evaluate Garbage Collection Performance 

 -XX:+PrintGCDetails 选项

开启这个选项, 在每次 GC 的时候都会输出 GC 信息, 例如在回收前后的存活对象的大小, 每一代的总可用空间, 每一次垃圾回收的时间长短.

-XX:+PrintGCTimeStamps 选项

输出 GC 的时间戳

jmap

jmap 是一个 JDK 命令行工具 (Windows 中没有), 它用来输出 JVM 的内存相关的统计, 如果没有任何选项参数, 它会输出加载的对象列表. 需要更详细的信息, 可以使用 -heap, -histo, -permstat 参数.

-heap 参数用来获取垃圾收集器, 回收算法 (例如 parallel garbage collection 的线程数) 堆配置信息, 堆的内存使用等信息.

-histo 可以用来获取 class 级别的堆信息. 他会输出每个 class 的实例数以及占用内存数, 以及他们的全限定名.

-permstat 可以用来输出 permanent 区的对象统计, 主要是一些 class 的元数据.

jstat

jstat 使用 HotSpot JVM 内部指令来输出程序运行时的资源占用和性能信息. 他可以用来诊断性能问题, 特别是跟堆大小以及垃圾回收相关的问题.

HPROF: Heap Profiler 

HRPOF 是一个简单的 profiler agent. 他是一个使用 Java Virtual Machine Tools Interface (JVM TI) 的 JVM 动态链接库接口. 它可以输出一些监测信息到文件中, 这个文件以后可以被性能分析工具用来分析性能问题.

HPROF 可以提供 CPU 使用信息, heap 分配统计, monitor 竞争监测等. 另外, 他还可以输出完整的 heap dump, 并报告 JVM 中所有的 monitor 和线程状态. HPROF 在分析性能问题, 锁竞争, 内存碎片以及其他问题时很有用.

HAT: Heap Analysis Tool 

HAT 可以用来分析内存泄露问题. 他可以用来浏览由 HPROF 生成的快照文件.

5. Key Options Related to Garbage Collection 

一些常用的 JVM 参数, "m" 或 "M" 表示 megabytes , "k" 或 "K" 表示 kilobytes, "g" 或 "G" 表示 gigabytes

Garbage Collector Selection

Option

Garbage Collector Selected

–XX:+UseSerialGC

Serial 串行垃圾收集器

–XX:+UseParallelGC

Parallel 并行垃圾收集器

–XX:+UseParallelOldGC

Parallel compacting 旧的并行垃圾收集器

–XX:+UseConcMarkSweepGC

Concurrent mark–sweep (CMS)

Garbage Collector Statistics

Option

Description

–XX:+PrintGC

Outputs basic information at every garbage collection. 输出每次垃圾收集的基本信息

–XX:+PrintGCDetails

Outputs more detailed information at every garbage collection. 输出每次垃圾收集的具体信息

–XX:+PrintGCTimeStamps

Outputs a time stamp at the start of each garbage collection event. Used with –XX:+PrintGC or –XX:+PrintGCDetails to show when each garbage collection begins.

输出 GC 时间戳, 可以跟以上两个命令一起使用

Heap and Generation Sizes

Option

Default

Description

–Xmsn

See Section 5

Initial size, in bytes, of the heap. 初始堆大小, 单位字节

–Xmxn

See Section 5

Maximum size, in bytes, of the heap. 最大堆大小, 单位字节

–XX:MinHeapFreeRatio=minimum and –XX:MaxHeapFreeRatio=maximum

40 (min) 70 (max)

Target range for the proportion of free space to total heap size. These are applied per generation. For example, if minimum is 30 and the percent of free space in a generation falls below 30%, the size of the generation is expanded so as to have 30% of the space free. Similarly, if maximum is 60 and the percent of free space exceeds 60%, the size of the generation is shrunk so as to have only 60% of the space free.

堆内空闲空间的大小比例, 这适用于所有 generation. 例如, 如果最小值是 30%, 那么当空闲空间小于 30% 的时候, 就会进行扩容. 而如果最大值是 60% 那么当空闲空间大于 60% 的时候, 堆就会进行缩减 

–XX:NewSize=n

Platform–dependent

Default initial size of the new (young) generation, in bytes. young 区的初始大小

–XX:NewRatio=n

2 on client JVM, 8 on server JVM

Ratio between the young and old generations. For example, if n is 3, then the ratio is 1:3 and the combined size of Eden and the survivor spaces is one fourth of the total size of the young and old generations.

young 区 和 old 区的大小比例. 如果是 3, 那么 young 与 old 区的比值为 1 : 3

–XX:SurvivorRatio=n

32

Ratio between each survivor space and Eden. For example, if n is 7, each survivor space is one–ninth of the young generation (not one–eighth, because there are two survivor spaces).

survivor 与 eden 的比值大小. 例如是 7, 那么 survivor 占 young 的比值是 1/9 (不是 1/8, 因为有 2 个 survivor 区)

–XX:MaxPermSize=n

Platform–dependent

Maximum size of the permanent generation. permanent 区最大值

Options for the Parallel and Parallel Compacting Collectors

Option

Default

Description

–XX:ParallelGCThreads=n

The number of CPUs

Number of garbage collector threads. GC 线程数

–XX:MaxGCPauseMillis=n

No default

Indicates to the collector that pause times of n milliseconds or less are desired. 期望的暂停时间(小于等于)毫秒数

–XX:GCTimeRatio=n

99

Number that sets a goal that 1/(1+n) of the total time be spent on garbage collection. GC 时间占程序时间的比值目标

Options for the CMS Collector

Option

Default

Description

–XX:+CMSIncrementalMode

Disabled

Enables a mode in which the concurrent phases are done incrementally, periodically stopping the concurrent phase to yield back the processor to the application.

启用增量模式, 定期的暂停回收让程序跑一跑

–XX:+CMSIncrementalPacing

Disabled

Enables automatic control of the amount of work the CMS collector is allowed to do before giving up the processor, based on application behavior.

启用 CMS 自动控制工作量

–XX:ParallelGCThreads=n

The number of CPUs

Number of garbage collector threads for the parallel young generation collections and for the parallel parts of the old generation collections.

Young 区并行收集以及 Old 的并行部分的并行线程数

 

6. 相关链接

HotSpot Garbage Collection and Performance Tuning

• Garbage Collection in the Java HotSpot Virtual Machine (http://www.devx.com/Java/Article/21977)

• Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine (http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html)

Ergonomics

• Server–Class Machine Detection (http://java.sun.com/j2se/1.5.0/docs/guide/vm/server–class.html)

• Garbage Collector Ergonomics

(http://java.sun.com/j2se/1.5.0/docs/guide/vm/gc–ergonomics.html)

• Ergonomics in the 5.0 JavaTM Virtual Machine

(http://java.sun.com/docs/hotspot/gc5.0/ergo5.html) Options

• JavaTM HotSpot VM Options

(http://java.sun.com/docs/hotspot/VMOptions.html)

• Solaris and Linux options

(http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/java.html)

• Windows options

(http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/java.html) Tools and Troubleshooting

• JavaTM 2 Platform, Standard Edition 5.0 Trouble–Shooting and Diagnostic Guide

(http://java.sun.com/j2se/1.5/pdf/jdk50_ts_guide.pdf )

• HPROF: A Heap/CPU Profiling Tool in J2SE 5.0

(http://java.sun.com/developer/technicalArticles/Programming/HPROF.html)

• Hat: Heap Analysis Tool

(https://hat.dev.java.net/) 

Finalization

• Finalization, threads, and the Java technology–based memory model

(http://devresource.hp.com/drc/resources/jmemmodel/index.jsp)

• How to Handle Java Finalization's Memory–Retention Issues

(http://www.devx.com/Java/Article/30192) Miscellaneous

  • J2SE 5.0 Release Notes

    (http://java.sun.com/j2se/1.5.0/relnotes.html)

  • JavaTM Virtual Machines

    (http://java.sun.com/j2se/1.5.0/docs/guide/vm/index.html)

  • Sun JavaTM Real–Time System (Java RTS)

    (http://java.sun.com/j2se/realtime/index.jsp)

  • General book on garbage collection: Garbage Collection: Algorithms for Automatic Dynamic Memory Management by Richard Jones and Rafael Lins, John Wiley & Sons, 1996. 

posted on 2014-06-08 21:26  ZimZz  阅读(2156)  评论(0编辑  收藏  举报