GC学习笔记之一
参考:
英文原文:cubrid,编译:ImportNew-王晓杰
译文地址: http://www.importnew.com/1993.html
1.GC优化很多时候就是指减少Stop-the-world发生的时间。
2.三代划分及按代回收的理论前提
- (1) 大多数对象会很快变得不可达。
- (2) 只有很少的由老对象(创建时间较长的对象)指向新生对象的引用这些假设我们称之为弱年代假设( weak generational hypothesis)。为了强化这一假设,HotSpot虚拟机将其物理上划分为两个–新生代(young generation)和老年代(old generation)。
3.三代的划分:
(1) 新生代(Young generation)
绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程我们称之为”minor GC“。
新生代GC处理机制
新生代可以被分为三个空间。一个伊甸园空间(Eden)、两个幸存者空间(Survivor )。一共有三个空间,其中包含两个幸存者空间。每个空间的执行顺序如下:
- a. 绝大多数刚刚被创建的对象会存放在伊甸园空间。
- b. 在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。
- c. 此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。
- d. 当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。
在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。
如果你仔细观察这些步骤就会发现,其中一个幸存者空间必须保持是空的。如果两个幸存者空间都有数据,或者两个空间都是空的,那一定标志着你的系统出现了某种错误。
需要注意的是HotSpot虚拟机使用了两种技术来加快内存分配。他们分别是是”bump-the-pointer“和“TLABs(Thread-Local Allocation Buffers)”。
Bump-the-pointer技术跟踪在伊甸园空间创建的最后一个对象。这个对象会被放在伊甸园空间的顶部。如果之后再需要创建对象,只需要检查伊甸园空间是否有足够的剩余空间。如果有足够的空间,对象就会被创建在伊甸园空间,并且被放置在顶部。这样以来,每次创建新的对象时,只需要检查最后被创建的对象。这将极大地加快内存分配速度。但是,如果我们在多线程的情况下,事情将截然不同。如果想要以线程安全的方式以多线程在伊甸园空间存储对象,不可避免的需要加锁,而这将极大地的影响性能。TLABs 是HotSpot虚拟机针对这一问题的解决方案。该方案为每一个线程在伊甸园空间分配一块独享的空间,这样每个线程只访问他们自己的TLAB空间,再与bump-the-pointer技术结合可以在不加锁的情况下分配内存。
(2)老年代(Old generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为”major GC“(或者”full GC“)。P.S.个人更喜欢叫他旧生代。
老年代GC处理机制
老年代空间的GC事件基本上是在空间已满时发生,执行的过程根据GC类型不同而不同,因此,了解不同的GC类型将有助于你理解本节的内容。
JDK7一共有5种GC类型:
- (a) Serial GC
- (b)Parallel GC
- (c)Parallel Old GC (Parallel Compacting GC)
- (d)Concurrent Mark & Sweep GC (or “CMS”)
- (e)Garbage First (G1) GC
其中,Serial GC不应该被用在服务器上。这种GC类型在单核CPU的桌面电脑时代就存在了。使用Serial GC会显著的降低应用的性能指标。现在,让我们共同学习每一种GC类型
(a) Serial GC (-XX:+UseSerialGC) 串行GC
新生代空间的GC方式我们在前面已经介绍过了,在老年代空间中的GC采取称之为标记-清扫算法”mark-sweep-compact“的算法。算法的第一步是标记老年代中依然存活对象。第二步,从头开始检查堆内存空间,清理并只留下依然幸存的对象。最后一步,从头开始,顺序地填满堆内存空间,并且将对内存空间分成两部分:一个保存着对象,另一个空着(压缩)。
(b) Parallel GC (-XX:+UseParallelGC) 并行GC
图 4: Serial GC 与 Parallel GC的区别
从上图中,你可以轻易地看出serial GC和parallel GC的区别,serial GC只使用一个线程执行GC,而parallel GC使用多个线程,因此parallel GC更高效。这种GC在内存充足以及多核的情况下会很有用,因此我们也称之为”throughput GC“。
(c) Parallel Old GC(-XX:+UseParallelOldGC) 并行旧生代GC
Parallel Old GC在JDK5之后出现。与parallel GC相比,唯一的区别在于针对老年代的GC算法。Parallel Old GC分为三步:标记-汇总-压缩(mark – summary – compaction)。汇总(summary)步骤与清理(sweep)的不同之处在于,其将依然幸存的对象分发到GC预先处理好的不同区域,算法相对清理来说略微复杂一点。
(d) CMS GC (-XX:+UseConcMarkSweepGC)
图 5: Serial GC & CMS GC
就像你从上图看到的那样, CMS GC比我之前解释的各种算法都要复杂很多。第一步初始化标记(initial mark)比较简单。这一步骤只是查找那些距离类加载器最近的幸存对象。因此,停顿的时间非常短暂。在之后的并行标记(concurrent mark)步骤,所有被幸存对象引用的对象会被确认是否已经被追踪和校验。这一步的不同之处在于,在标记的过程中,其他的线程依然在执行。在重新标记(remark)步骤,会再次检查那些在并行标记步骤中增加或者删除的与幸存对象引用的对象。最后,在并行交换( concurrent sweep )步骤,转交垃圾回收过程处理。垃圾回收工作会在其他线程的执行过程中展开。一旦采取了这种GC类型,由GC导致的暂停时间会极其短暂。CMS GC也被称为低延迟GC。它经常被用在那些对于响应时间要求十分苛刻的应用之上。
CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:
初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。
当然,这种GC类型在拥有stop-the-world时间很短的优点的同时,也有如下缺点:
- • 它会比其他GC类型占用更多的内存和CPU
- • 默认情况下不支持压缩步骤
在使用这个GC类型之前你需要慎重考虑。如果因为内存碎片过多而导致压缩任务不得不执行,那么stop-the-world的时间要比其他任何GC类型都长,你需要考虑压缩任务的发生频率以及执行时间。
(e) G1 GC
最后,我们来学习垃圾回收优先(G1)GC类型。
图 6: G1 GC的结构
如果你想要理解G1,首先你要忘记你所学过的新生代和老年代的概念。正如你在上图所看到的,每个对象被分配到不同的格子,随后GC执行。当一个区域装满之后,对象被分配到另一个区域,并执行GC。这中间不再有从新生代移动到老年代的三个步骤。这个类型是为了替代CMS GC而被创建的,因为CMS GC在长时间持续运作时会产生很多问题。
G1最大的好处是性能,他比我们在上面讨论过的任何一种GC都要快。但是在JDK 6中,他还只是一个早期试用版本。在JDK7之后才由官方正式发布。就我个人看来,NHN在将JDK 7正式投入商用之前需要很长的一段测试期(至少一年)。因此你可能需要再等一段时间。并且,我也听过几次使用了JDK 6中的G1而导致Java虚拟机宕机的事件。请耐心的等到它更稳定吧。
(3)持久代( permanent generation )也被称为方法区(method area)。
他用来保存类常量以及字符串常量。因此,这个区域不是用来永久的存储那些从老年代存活下来的对象。这个区域也可能发生GC。并且发生在这个区域上的GC事件也会被算为major GC。
这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域(新生代、旧生代)不同,GC不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
如果老年代的对象需要引用一个新生代的对象,会发生什么呢?
为了解决这个问题,老年代中存在一个”card table“,他是一个512 byte大小的块。所有老年代的对象指向新生代对象的引用都会被记录在这个表中。当针对新生代执行GC的时候,只需要查询card table来决定是否可以被收集,而不用查询整个老年代。这个card table由一个write barrier来管理。write barrier给GC带来了很大的性能提升,虽然由此可能带来一些开销,但GC的整体时间被显著的减少。
图 2: Card Table 结构
参考:
英文原文:cubrid,编译:ImportNew-王晓杰
译文地址: http://www.importnew.com/1993.html
- 大小: 58.3 KB
- 大小: 134.4 KB
- 大小: 11.1 KB
- 大小: 38.9 KB
分享到:
相关推荐
【良葛格Java学习笔记】 本笔记主要涵盖了Java编程语言的核心概念和技术,旨在帮助初学者以及有一定基础的开发者深入理解并掌握Java。Java作为一种广泛应用于企业级应用开发、移动开发(尤其是Android)以及大数据...
【Java SE学习笔记】是针对Java初学者的一份详实的学习资源,主要涵盖了Java的基础知识、进阶概念以及编程实践。这份笔记以HTML格式呈现,方便读者在线阅读或下载后离线浏览。以下是对这份笔记可能包含的重要知识点...
**JAVA SE学习笔记** 在Java SE(标准版)的学习中,我们主要关注的是Java编程语言的基础和核心特性,包括但不限于语法、数据类型、控制结构、类与对象、接口、异常处理、多线程、集合框架、输入/输出(I/O)系统、...
Java是一种广泛使用的面向对象的编程语言,其基础知识构成了"Core Java"的学习内容。在学习Java时,遵循"多花时间、多动手、多问题"的原则至关重要,因为理论理解与实践操作相结合能更好地掌握知识。 1. **Java语法...
### Java学习笔记知识点总结 #### 一、JVM与内存管理 **1.1 JVM基本概念** - **JVM(Java Virtual Machine)**: Java虚拟机是执行Java字节码的虚拟机,它提供了运行Java程序所需的环境。 **1.2 线程** - **线程...
### Core Java 基础学习笔记 #### 一、Java基础知识概述 Java 是一门面向对象的编程语言,具有跨平台的特性。Java 的程序需要经过两步处理:首先,源代码通过编译器生成字节码文件(.class 文件);其次,字节码...
这篇“java学习笔记”可能包含了从基础到进阶的各种Java编程概念和技术。以下是对这些笔记可能涵盖的一些关键知识点的详细说明: 1. **Java基础知识**: - **语法**:包括变量声明、数据类型(如整型、浮点型、...
Java学习笔记之大鹏JAVA终级总结,是针对Java编程语言深入学习和面试准备的一份综合资料。这份总结涵盖了从基础知识到高级概念的多个方面,旨在帮助初学者理解和掌握Java的核心概念,同时解决面试中可能出现的关键...
### CoreJava 学习笔记概览 #### 编译与运行 Java 程序 **编译命令**:`javac` - **基本语法**:`javac ***.java` - **命令行参数**: - `-g`:生成所有调试信息。 - `-g:none`:不生成任何调试信息。 - `-...
### Java学习笔记——Java基础知识整理 #### 一、Java技术入门 Java是一种广泛使用的编程语言,因其跨平台性、安全性和高效性而受到青睐。Java最初由Sun Microsystems开发,并于1995年首次发布。 ##### 1. Sun ...
【JAVA学习精细笔记】 Java是一种高级编程语言,以其“一次编写,到处运行”的特性而闻名。它的源代码首先通过编译器转化为字节码(.class文件),这些字节码随后由Java虚拟机(JVM)解释执行。JVM是Java运行的核心...
Java对多线程的支持是其强大特性之一。笔记中可能会介绍Thread类的创建与管理,同步控制(synchronized关键字、wait/notify机制、Lock接口)、线程池(ExecutorService、ThreadPoolExecutor)等知识点。 3. **序列...
【Java学习笔记.zip】是一个包含了全面的Java学习资源的压缩包,主要涵盖了Java基础知识、JVM虚拟机原理、操作系统概念、计算机网络知识以及与数据库相关的笔记。这个资料包显然是为那些刚开始学习Java编程或者准备...
在讨论Java编程思想学习笔记时,首先需要了解的是Java语言的平台无关性,而这一特性正是通过Java虚拟机(JVM)得以实现的。JVM作为Java程序设计的关键组成部分,对于Java开发人员来说是必须掌握的基础知识。在该学习...
### 逐步深入的Java学习笔记知识点总结 #### 一、Java环境配置 1. **JAVA_HOME**: 配置JDK的目录。这是Java环境的基本配置之一,用于指示系统JDK安装的位置。 - **Linux系统**: ```bash JAVA_HOME=/opt/jdk1.5.0...
健壮性:java的健壮性与自动垃圾回收机制有关,自动垃圾回收机制简称GC机制,java语言运行过程中产生的垃圾是自动回收的,不需要程序员关心。 可移植性:java程序可以做到一次编译,到处运行。在Windows操作系统上...
Spring 是 Java 开发中最流行的框架之一,提供依赖注入(DI)和面向切面编程(AOP),简化了企业级应用的开发。它还包含 Spring MVC 用于 web 开发,Spring Boot 用于快速启动应用,以及 Spring Data 支持多种数据...
### Java学习笔记——基础知识详解 #### 一、Java开发环境(JDK)与运行环境(JRE) Java技术的核心在于其强大的跨平台能力,这主要得益于Java的两大环境:JDK(Java Development Kit)和JRE(Java Runtime ...
Java垃圾回收(Garbage Collection, 简称GC)是Java编程语言中一项重要的自动内存管理机制,...通过阅读"Java学习笔记_垃圾回收.pdf",你将进一步深入理解这个主题,掌握如何在实际项目中有效利用和优化垃圾回收机制。