java垃圾收集机制
jvm的gc原理

jvm的gc原理JVM的GC原理一、概述JVM(Java虚拟机)是Java程序运行的环境,其中最重要的组成部分之一就是垃圾回收(Garbage Collection,简称GC)机制。
GC的作用是自动管理程序中的内存,及时释放不再使用的对象,以避免内存泄漏和内存溢出的问题。
本文将对JVM的GC原理进行详细介绍。
二、垃圾回收算法1. 标记-清除算法标记-清除算法是最基本的垃圾回收算法之一。
它的过程分为两个阶段:标记阶段和清除阶段。
在标记阶段,GC会从根节点(一般是程序中的静态变量和栈中的引用)开始,递归地遍历对象图,标记出所有被引用的对象。
在清除阶段,GC会遍历整个堆,清除所有未被标记的对象。
2. 复制算法复制算法是针对标记-清除算法的改进。
它将堆分为两个区域,每次只使用其中一个区域。
当一个区域的对象被标记后,将其复制到另一个区域中,然后清除原来的区域。
这样可以解决碎片问题,但是需要额外的空间来存储复制的对象。
3. 标记-整理算法标记-整理算法是对标记-清除算法的改进。
它的过程与标记-清除算法类似,但是在清除阶段,标记-整理算法会将存活的对象向一端移动,然后清除边界外的所有对象。
这样可以解决碎片问题,并且不需要额外的空间。
4. 分代算法分代算法是针对对象的生命周期不同而提出的。
一般来说,对象的生命周期可以分为年轻代和老年代。
年轻代中的对象生命周期较短,老年代中的对象生命周期较长。
分代算法将堆分为年轻代和老年代两个区域,分别采用不同的垃圾回收算法。
年轻代一般使用复制算法,老年代一般使用标记-清除算法或标记-整理算法。
三、GC的执行过程1. 初始标记初始标记阶段是GC的第一步,它的目的是标记出所有的根对象,并且停止所有的应用线程。
这个过程是短暂的,因为只需要标记出与根对象直接关联的对象。
2. 并发标记并发标记阶段是GC的核心步骤,它的目的是通过并发执行来标记出所有的存活对象。
在这个阶段,GC会遍历整个堆,标记出与根对象直接或间接关联的存活对象。
javaGC垃圾回收机制G1、CMS

javaGC垃圾回收机制G1、CMSCMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间。
对于要求服务器响应速度的应⽤上,这种垃圾回收器⾮常适合。
在启动JVM参数加上-XX:+UseConcMarkSweepGC ,这个参数表⽰对于⽼年代的回收采⽤CMS。
CMS采⽤的基础算法是:标记—清除。
使⽤场景:1、应⽤程序对停顿⽐较敏感,并且在应⽤程序运⾏的时候可以提供更⼤的内存和更多的CPU2、在JVM中,有相对较多存活时间较长的对象(⽼年代⽐较⼤)会更适合使⽤CMS。
为解决CMS算法产⽣空间碎⽚和其它⼀系列的问题缺陷,HotSpot提供了另外⼀种垃圾回收策略,G1(Garbage First)算法,通过参数-XX:+UseG1GC来启⽤,该算法在JDK 7u4版本被正式推出,G1垃圾收集算法主要应⽤在多CPU⼤内存的服务中,在满⾜⾼吞吐量的同时,竟可能的满⾜垃圾回收时的暂停时间,下⾯是官⽅介绍:The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories.It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbagecollector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:Can operate concurrently with applications threads like the CMS collector.Compact free space without lengthy GC induced pause times.Need more predictable GC pause durations.Do not want to sacrifice a lot of throughput performance.Do not require a much larger Java heap.G1采⽤了另外⼀种完全不同的⽅式组织堆内存,堆内存被划分为多个⼤⼩相等的内存块(Region),每个Region是逻辑连续的⼀段内存,G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。
java自动垃圾回收机制

java⾃动垃圾回收机制前⾔:相⽐C++,java做的⼀⼤改进是将复杂的内存管理抽离出来交给jvm去处理,让码农不再时刻盯着内存泄漏的问题,可以更专注于业务逻辑的开发。
java的GC机制是和其内存模型相关联的,⽽GC的核⼼内存区域是内存中的堆区。
java堆区按对象的存活时间被分为了年轻代(eden区+s0区+s1区)和⽼年代(tentired区),java堆的按代区分其实是为了其垃圾回收的分代收集机制打开了⽅便之门。
java的GC收集器会在不同的分代上使⽤不同的垃圾收集策略。
GC其实主要需要解决两个问题:哪些是垃圾?如何清理垃圾?在解决这两个问题上涉及到下⾯的⽅法论:1.垃圾对象判定⽅法引⽤计数法:在C++的智能指针中使⽤了这种⽅式去做内存的⾃动回收。
即在对象⽣成时维护⼀个对该对象引⽤次数的计数器,对象初次⽣成时计数器值为1,每增加⼀个到该对象的引⽤,计数器加1,每减少⼀个引⽤(如引⽤变量赋值null,或引⽤变量离开作⽤域),计数器减1,计数器为零时,对象内存会被⾃动回收。
该⽅法的问题是存在内存泄漏的隐患,如对象相互引⽤、循环引⽤等情况相互引⽤:public class ReferenceCountingGc {Object instance = null;public static void main(String[] args) {ReferenceCountingGc objA = new ReferenceCountingGc();ReferenceCountingGc objB = new ReferenceCountingGc();objA.instance = objB;objB.instance = objA;objA = null;objB = null;}} 例⼦中两个new出来的对象ReferenceCountingGc由于通过内部的变量instance引⽤着对⽅,两个对象的引⽤计数都为1。
Java垃圾回收CMS、G1、ZGC

Java垃圾回收CMS、G1、ZGC在阐述三种垃圾收集器以前,先普及下⼏种垃圾回收算法①、引⽤计数算法:通过对象被引⽤的次数确定对象是否被使⽤,缺点是⽆法解决循环引⽤的问题。
②、复制算法:分为from块和to块,开始在from块,回收时将from块存活的对象复制到to块,将from块清空,to块变from块,from块变to块,缺点是内存使⽤率较低。
③、标记清除算法:分为标记对象和标记不在使⽤的对象两个阶段,缺点是会产⽣内存碎⽚。
④、标记整理算法:与标记清除算法相同,不过在清楚后会进⾏内存整理。
⑤、分代回收算法:当前的商业虚拟机的垃圾收集都是采⽤“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为⼏块。
⼀般是把堆划分为新⽣代和⽼年代,这样就可以根据各个年代的特点采⽤最适合的收集算法。
在新⽣代中,每次垃圾收集时都发现有⼤批对象死去,只有少量存活,那就采⽤复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
⽽⽼年代中因为对象存活率⾼、没有额外空间对它进⾏分配担保,就必须使⽤“标记-清理”或者“标记-整理”算法来进⾏回收。
如上图,Eden⽤于分配新的内存空间,当第⼀轮回收后剩下的对象被放到Survivor1,此时年龄为1。
第⼆次剩下的对象则年龄为1,第⼀次的年龄为2,他们被复制到Survivor2。
当再次回收的时候,⼜由Survivor2转换到Survivor1容器,他们两个反复替换。
当对象的年龄成长到8以后,被移动到⽼年代。
永久代⼜叫⽅法区。
Minor GC 年轻代的回收Major GC 年⽼代的回收jvm提供的年轻代回收算法属于复制算法,CMS、G1,ZGC属于标记清除算法。
⼀、CMS收集器 Concurrent Mark Sweep,以获取最短回收停顿时间为⽬标的收集器,基于并发“标记清理”实现。
JDK1.7之前的默认垃圾回收算法,并发收集,停顿⼩。
Java教学中垃圾收集机制问题的探讨

作 .就 会 导致 该 变 量所 占用 的 内存 空 问 无 法 释 放 .直 到 程 序 终 4 熟悉 与垃 圾 回 收 有关 的 一 些 常 用 方 法 . Jv a a语 言 提 供 了一 些 和 垃 圾 回收 有关 的方 法 。 以便 在 必 要 止 。 我 们 称 这 种 无 法 回 收 的 内 存 空 间 为 ” 内 存 漏 洞 ( m r Me oy维普资讯 来自20 0 7年第 6期
福
建
电
脑
25 0
Jv 教学 中垃圾收集机制 问题 的探讨 aa
付 兵
(长 江 大 学 计 算 机科 学 学 院 湖 北 荆 州 4 4 2 ) 30 3
【 要】 摘 :本文对 Jv 教 学 中垃圾 收集机制 问题进行 了探 讨。对比 C + 内存泄露 问题 引入 Jv aa +的 aa垃圾收集机制 , 并说
一
或 内存 . 必须 由程 序 员 自行 声 明产 生 和 回收 。 程 序 为某 个 变 是 可 访 问 的 .这对 于可 能 有 页 面 交 换 的 堆 的 虚 拟 内 存 系统 有 非 都 若 量 分 配 了 内存 .但 变量 使 用 完 之 后 却 没 有 相 应 执 行 内存 释 放 操 常 负 面 的 性 能影 响 . 另外 它 还 容 易 使 堆 产 生碎 片 。
法 来 实 现 资 源 自动 回 收 的 功 能 。正 因 为 Jv aa中 的垃 圾 收集 机 制 达 的对 象 . 记 出可 到 达对 象 。 下 的 就 是 垃 圾 对 象 。 然后 就对 标 剩 复 杂 而 特 殊 . 及 到 的 多 是 内存 管理 问题 .这 使 它 成 为 Jv 涉 a a教 堆 进 行 清 除 .所 有 没 有 标 记 的对 象 都 作 为 垃 圾 回 收并 返 回空 闲
小议Java虚拟机的垃圾收集机制

软 件 行 业 中 ,aa 言 正 以不 可 抵 挡 的流 行 趋 势 迅 速 流 传 , 了支 Jv 语 除
持平 台无关性这一显著优点 以外 , 另一方 面就是 利用 Jv aa虚拟机 Jv aa Viu l c ie简 称 J M) 供 的 自动 垃 圾 回 收机 制 , 于 释 放 那 些 不 r a Mahn。 t V 提 用
42 E oktv 的使 用 . AJ c ij M B R
Jv语 言在创建类 的实例( aa 对象) 时使用 nw运算符为其分配空间 , e
但 它们不像 cC +语言那样需要程序代码来显式 释放 。 ,+ 一般来说 , 它都 是由系统 J, 、 M提供的 自动垃圾回收机 制来负责 的。垃圾 回收是一种动 态存储管理技术 , 自动地释放不再被程序引用的对象 , 它 按照特定的垃 圾收集算法来实现资源 自动回收的功能 。尽管 Jv 语言规范没有明确 aa 地说明 J M使用哪种垃圾 回收算法 , V 但是任何一种垃圾 收集算法一般 要做 2件基本的事情 : 1发现无用信息对象 ;2 回收被无用对象 占用 () () 的 内存空间 , 使该空间可被程序再次使用。 事实上 ,除 了释放没用 的对象 ,垃圾收集也可 以清除 内存记 录碎 片。 由于创建对象和垃圾收集器释放丢弃对象所 占的内存空间 , 内存会 出现碎片。 片是分配给对象的内存块之 间的空 闲内存洞 。 碎 碎片整理将 所 占用的堆内存移 到堆 的一端 , M将整理 出的内存分配 给新 的对象。 J V 垃圾收集能 自动释放 内存空 间, 减轻编程 的负担。这使 J M具有 V 些显著优点。 首先 , 它能使编程效率提高。 在没有垃圾收集机制的时 候, 可能要花费许多时间来解决一个存储器的存储 与释放 问题 。 而垃圾 收集机制可大大缩短时间。其次它是 Jv 语言安全性 策略的一个 重要 aa 部份 , 充分保 护了程 序的完整性 。 垃圾收集的一个潜 在的缺点是它 的开销影 响程序性能 。J VM必须 追踪运行程序中有用的对象 , 而且最终释放没用的对象。 这一个过程需 要 花费处理器的时间。 其次 垃圾收集算法的不完备性 , 早先采用的某些 垃圾 收集算法就不能保证 10 0 %收集到所有的废弃 内存 。 当然 随着垃圾
javagc回收机制

javagc回收机制即java垃圾回收机制,是自动的内存管理机制,它可以在程序执行时自动回收无用的对象,以释放内存空间。
Java 中的垃圾回收机制主要包括以下几个方面:
1. 对象的创建和销毁:当一个对象被创建时,Java 虚拟机会为其分配一块内存空间,并记录其在内存中的位置。
当对象不再被引用时,Java 虚拟机会将其标记为垃圾对象,并在适当的时候回收它所占用的内存空间。
2. 垃圾收集算法:Java 中使用的垃圾收集算法主要有标记-清除算法和复制算法。
标记-清除算法会先标记所有还在使用中的对象,然后清除所有未被标记的对象;复制算法则会将内存分为两个区域,将还在使用中的对象复制到其中一个区域,然后清除另一个区域中的所有对象。
3. 垃圾收集器的选择和配置:Java 中提供了多种垃圾收集器,如Serial GC、Parallel GC、CMS GC 等。
可以根据程序的特点和运行环境的需求选择合适的垃圾收集器和配置参数,以达到最优的垃圾回收效果。
4. 垃圾回收的影响:垃圾回收会占用一定的系统资源,可能会影响程序的性能。
因此,在进行垃圾回收时需要注意控制回收的频率和时间,以避免对程序的性能造成过大的影响。
总的来说,Java 中的垃圾回收机制是一个自动化的、高效的内存管理机制,可以帮助开发人员避免内存泄漏等问题,提高程序的稳定性和可靠性。
Java8的GC垃圾回收

Java8的GC垃圾回收Java垃圾回收概况Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C的主要区别之⼀,作为Java开发者,⼀般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。
这是因为在Java虚拟机中,存在⾃动内存管理和垃圾清扫机制。
概括地说,该机制对JVM中的内存进⾏标记,并确定哪些内存需要回收,根据⼀定的回收策略,⾃动的回收内存,永不停息的保证JVM 中的内存空间,防⽌出现内存泄露和溢出问题。
关于JVM,需要说明⼀下的是,⽬前使⽤最多的Sun公司的JDK中,⾃从1999年的JDK1.2开始直⾄现在仍在⼴泛使⽤的JDK6,其中默认的虚拟机都是HotSpot。
2009年,Oracle收购Sun,加上之前收购的EBA公司,Oracle拥有3⼤虚拟机中的两个:JRockit和HotSpot,Oracle也表明了想要整合两⼤虚拟机的意图,但是⽬前在新发布的JDK8中,默认的虚拟机仍然是HotSpot,因此本⽂中默认介绍的虚拟机都是HotSpot,相关机制也主要是指HotSpot的GC机制。
Java GC机制主要完成3件事:确定哪些内存需要回收确定什么时候需要执⾏GC如何执⾏GC经过这么长时间的发展,Java GC机制已经⽇臻完善,⼏乎可以⾃动的为我们做绝⼤多数的事情。
然⽽,如果我们从事较⼤型的应⽤软件开发,曾经出现过内存优化的需求,就必定要研究Java GC机制。
学习Java GC机制,可以帮助我们在⽇常⼯作中排查各种内存溢出或泄露问题,解决性能瓶颈,达到更⾼的并发量,写出更⾼效的程序。
我们将从4个⽅⾯学习Java GC机制,1,内存是如何分配的;2,如何保证内存不被错误回收(即:哪些内存需要回收);3,在什么情况下执⾏GC以及执⾏GC的⽅式;4,如何监控和优化GC机制。
内存是如何分配的这⾥所说的内存分配,主要指的是在堆上的分配,⼀般的,对象的内存分配都是在堆上进⾏,但现代技术也⽀持将对象拆成标量类型(标量类型即原⼦类型,表⽰单个值,可以是基本类型或String等),然后在栈上分配,在栈上分配的很少见,我们这⾥不考虑,接下来我们⼀起来了解下内存分区,对我们后⾯学习的有所帮助。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二、垃圾收集的基本原理:
2.1 JVM 中内存的划分
垃圾收集器对 Java 程序员来说,基本上是透明的,但是只有了解 GC 的工作 原理、如何优化 GC 的性能、如何与 GC 进行有限的交互,才能提高整个应用程序 的性能、全面提升内存的管理效率,为了说明其工作方式,我们首先看看内存中 几种常用的存放数据的地方: (1) 堆栈(Stack) : 位 于常规 RAM(随机访问存储器)区域,但可通过它的 “堆栈指针”获得处理器的直接支持。堆栈指针若向下移,会创建新的内存;若 向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次 于 CPU 的寄存器。创建程序时,Java 编译器必须准确地知道堆栈内保存的所有
2、基于 Tracing 算法、 Compacting 算法的 “标记和清除 (make-and- sweep)”方式:对于常规性的应用,标记和清除显得非常慢,但一旦知道自己 不产生垃圾,或者只产生很少的垃圾,它的速度就会非常快。标记和清除(make -and-sweep)采用的逻辑:基于 Tracing 算法从堆栈和静态存储区域开始,并 跟踪所有引用,寻找活动对象。然而,每次发现一个活动对象的时候,就会设置 一个标记(一个位或多个位) ,为那个对象作上“记号”。但此时尚不收集那个 对象。只有在标记过程结束,清除过程才正式开始。在清除过程中,不复存活的 对象会被释放然而,不会进行任何形式的复制(这时的堆中被使用的空间呈现不 连续的状态) 。所以假若收集器决定使这个断续的内存堆密集(compact),它将 使用 Compacting 算法重新整理他所找到的对象:垃圾收集器将所有的对象移置 堆的一端。堆的另一端就变成了一个相邻的空闲内存区。收集器会对它移动的所 有对象的所有引用进行更新,这样这些引用能够在新的位置识别同样的对象。为 了 简 化 对 象 引 用 的 更 新 , compacting 算法 增 加 了 间 接 的 一 层 ( level of indirection) 。间接层通过句柄(handle)和句柄表实现。在这种情况下,对象 引用总是指向句柄表中同样的句柄入口。反过来,句柄入口包含了句柄的实际引 用。当 compacting 标记和清除垃圾收集器移动对象时,收集器在句柄表中只修 改实际的对象引用对句柄入口的所有引用没有受到影响。 虽然使用句柄表简化了
4
Java 垃圾收集机器-Garbage Collector
发现这个问题,就得通过后续过程才能找到。 但是在有的情况下将使得“复制式垃圾收集器”显得效率极为低下,比如随 着程序进入了稳定状态之后,它几乎不产生或产生很少的垃圾。尽管如此,这时 的一个“复制式垃圾收集器”仍会将所有内存从一处复制到另一处,这显得非常 浪费。更糟的是:程序中的对象不仅不死亡,而且一个个都很庞大,对两个大的 内存堆管理也将成为不必要的消耗。
2
Java 垃圾收集机器-Garbage Collector
数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上 和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些 Java 数据 要保存在堆栈里——特别是对象的引用(也可称为对象的引用变量) ,但 Java 中的对象不会放在其中。 (2) 堆(Heap)。一种常规用途的内存池(也在 RAM 区域) ,其中保存了 Java 对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不 必知道要从堆里分配多少存储空间, 也不必知道存储的数据要在堆里停留多长的 时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需 用 new 命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保 存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时 会花掉更长的时间!这是导致 Java 性能不佳的因素之一。 SUN 的 JVM 使用分代方式(Generation)管理 堆 空 间 , “代”分配给新旧对象 的内存池。这些对象的不断积累会导致一个的内存状态,从而推动垃圾收集的开 始。如图说明了 SUN 的 JVM 中堆空间粗略的划分。
如图所 示 , 年 轻的 一 代 包 括年 轻的 对 象空 间( eden )和 两 个存 活 (survivor)空间(SS#1 和 SS#2) 。新对象被分配到 eden 中,那些存活较久的 对象则会从年轻的一代转移到老一代中。图中的 Perm 段叫做永久代(permanent generation) ,它保存了 JVM 的类和方法对象。 (3) 静态存储(Static)。这儿的“静态”(Static)是指“位于固定位置” (尽管也在 RAM 里)或是有且仅有一份。程序运行期间,静态存储的数据将随时 等候调用。可用 static 关键字指出一个对象的特定元素是静态的。但 Java 对象 本身永远都不会置入静态存储空间。
2.2 对象在内存中的分配
了解了内存中这些存放数据的方式后, 我们先来看看 C++中存放对象的机制: 在 C++中,对象可以是在堆栈中创建的,这样可达到更快的速度。然而,在 C++ 里创建“内存堆”(Heap)对象通常会慢得多。这种内存堆实际是一个大的内存 池,要求必须进行再循环(再生) 。这里可以把 C++的 Heap 想象是一块场地,在 这里面中每个对象不断监视属于自己的地盘, 他们可能在以后的某个时刻不再继 续占用目前所占用的空间,即释放后的内存会在堆里留下一个洞,所以再调用
一、引言:
在面向对象的程序设计中,我们肯定是在不停的产生对象,而产生的每个对 象为了生存,都需要动用资源,尤其是内存资源。当对象不需要内存,就该加以 清除,是资源可被释放、可再被使用。在程序设计的环境中:典型的情况是我们 首先产生对象,比如使用 new 关键字来创建对象,同时返回该对象的一个引用 (C++中该引用可能是个指针) ,之后我们通过该引用使用这个对象,当我们不再 使用该对象, 或是该对象失去对它的所有引用时, 它就应该被摧毁。 在 C,C++ 或 其它语言中,程序员负责取消分配内存。有时,这是一件很困难的事情。因为你 并不总是事先知道内存应在何时被释放。当在系统中没有能够被分配的内存时, 可导致程序瘫痪,这种程序被称作具有内存漏洞。在 Java 编程语言中解除了程 序员取消分配内存的责任, 它可提供一种系统级线程以跟踪每一存储器的分配情 况。这种系统级线程就是垃圾收集机器,在 Java 虚拟机的空闲周期,垃圾收集 线程检查并释放那些可被释放的存储器。垃圾收集在 Java 技术程序的生命周期 中自动进行,它解除了取消分配内存的要求,并避免了存储器漏洞。然而,它的 运行时间却是非确定的,因此我们必须小心。
Java 垃圾收集机器-Garbage Collector
一、引言:·································································· 2 二、垃圾收集的基本原理:············································· 2 2.1 JVM 中内存的划分··············································· 2 2.2 对象在内存中的分配············································· 3 2.3 垃圾收集的基本原理与算法····································4 三、与垃圾收集器交互··················································· 7 3.1 FINALIZE ()方法·················································· 7
12
3.2.1 软引用········································································ 13 3.2.2 弱引用········································································ 14 3.2.3 虚引用········································································· 15
四、总结··································································· 16
1
Java 垃圾收集机器-Garbage Collector
Java 垃圾收集机器-Garbage Collector
[摘 要]:本文详细讨论了 Java 垃圾收集机制的基本原理,并结合 Java 语言特 性, 介绍利用 Java 垃圾收集机制提高程序的健壮性和性能的基本方法。 [关键词]:Garbage collector,Heap, Reference, 对象,JVM
3.1.1 Finalize()用处之一:观察··············Finalize()用处之二:再生································ 11
3.2
NG.REF 包··················································
3
Java 垃圾收集机器-Garbage Collector
new 的时候,存储分配机制必须进行某种形式的搜索,使新对象能够利用已经存 在的空洞,否则就会很快用光堆的存储空间。之所以内存堆的分配会在 C++里对 性能造成如此重大的性能影响,对可用内存的搜索正是一个重要的原因。所以创 建基于堆栈的对象要快得多。 而在 Java 中的内存堆(Heap)更像一条传送带:每次分配了一个新对象后, “Heap 指针”都会朝前移动,这意味着对象存储空间的分配可以达到非常快的 速度。因为“Heap 指针”只是单纯的往前移动至未经分配的区域,所以它与 C++ 的堆栈分配方式几乎是不相上下的(当然,在数据记录上会多花一些开销,但要 比搜索存储空间快多了) 。但是如果只是按那种方式分配,最终就要求进行大量 的内存页面交换(这对性能的发挥会产生巨大干扰) ,而且终究会用光内存,出 现内存分页错误 (page fault)。所以 Java 引入了“垃圾收集器”。它在收集“垃 圾”的同时,也负责重新紧密排列(compact)堆里的所有对象,消除内存空洞, 将“堆指针”移至尽可能靠近传送带开头的地方,远离发生(内存)分页错误的 地点。 垃圾收集器会重新安排所有东西, 使其成为一个高速、 无限自由的堆模型 , 同时游刃有余地分配存储空间。但是垃圾收集时的代价是非常高昂的,这也是导 致 Java 性能不佳的因素之一。