- 浏览: 482253 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
alvin198761:
renzhengzhi 写道我参与过12306余票查询系统的开 ...
别给12306 辩解了 -
renzhengzhi:
我参与过12306余票查询系统的开发,用户请求被前面3层缓存拦 ...
别给12306 辩解了 -
renzhengzhi:
写的很好。
JAVA线程dump的分析 -
liyonghui160com:
说好的附件呢
分布式服务框架 Zookeeper -- 管理分布式环境中的数据 -
ghpaas:
orbeon作为xforms标准的实现,不论其设计器还是运行时 ...
XForms 1.1 中文翻译—第1章 关于XForms标准
垃圾收集的好处是无可争辩的 ―― 可靠性提高、使内存管理与类接口设计分离,并使开发者减少了跟踪内存管理错误的时间。著名的悬空指针和内存泄漏问题在 Java 程序中再也不会发生了(Java 程序可能会出现某种形式的内存泄漏,更精确地说是非故意的对象保留,但是这是一个不同的问题)。不过,垃圾收集不是没有代价的 ―― 其中包括对性能的影响、暂停、配置复杂性和不确定的结束 (nondeterministic finalization)。 一个理想的垃圾收集实现应该是完全不可见的 ―― 没有垃圾收集暂停、没有因为垃圾收集而产生的 CPU 时间损失、垃圾收集器不会与虚拟内存或者缓存有负面的互动,并且堆不需要大于应用程序的 驻留空间(即堆占用)。当然,没有十全十美的垃圾收集器,但是垃圾收集器在过去十年中已经有了很大改进。 1.3 JDK 包括三种不同的垃圾收集策略,1.4.1 JDK 包括六种垃圾收集策略以及 12 种以上用于配置和优化垃圾收集的命令行选项。它们有什么不同?为什么需要有这么多选项? 不同的垃圾收集实现使用不同的策略来识别和收回不可到达的对象,它们与用户程序和调度器以不同的方式互动。不同类型的应用程序对于垃圾收集有不同的要求 ―― 实时应用程序会将要求收集暂停的持续时间短并且有限制,而企业应用程序可能允许更长时间和可预测性更低的暂停以获得更高的吞吐能力。 有几种垃圾收集的基本策略:引用计数、标记-清除、标记-整理 (mark-compact) 和复制。此外,一些算法可以以 增量 方式完成它们的工作(不需要一次收集整个堆,使得收集暂停时间更短),一些算法可以在用户程序运行时运行( 并发收集)。其他算法则必须在用户程序暂停时一次进行整个收集(即所谓的 stop-the-world收集器)。最后,还有混合型的收集器,如 1.2 和以后版本的 JDK 使用的分代收集器,它对堆的不同区域使用不同的收集算法。 在对垃圾收集算法进行评价时,我们可能要考虑以下所有标准: 不管选择什么算法,硬件和软件的发展使垃圾收集更具有实用性。20 世纪 70 和 80 年代的经验研究表明,对于大型 Lisp 程序,垃圾收集消耗 25% 到 40% 的运行时。垃圾收集还不能做到完全不可见,这肯定还有很长的路要走。 所有垃圾收集算法所面临的问题是相同的 ―― 找出由分配器分配的,但是用户程序不可到达的内存块。不可到达是什么意思?可以以两种方式之一访问内存块 ―― 或者用户程序在 根 (root)中有对这一内存块的引用,或者在另一个可到达的块中有对这个块的引用。在 Java 程序中,根是对静态变量中或者活跃的堆栈框架上的本地变量中所包含的对象的引用。可到达的对象集是指向关系下根集的传递闭包。 最直观的垃圾收集策略是引用计数。引用计数很简单,但是需要编译器的重要配合,并且增加了赋值 函数 (mutator)的开销(这个术语是针对用户程序的,是从垃圾收集器的角度来看的)。每一个对象都有一个关联的引用计数 ―― 对该对象的活跃引用的数量。如果对象的引用计数是零,那么它就是垃圾(用户程序不可到达它),并可以回收。每次修改指针引用时(比如通过赋值语句),或者当引用超出范围时,编译器必须生成代码以更新引用的对象的引用计数。如果对象的引用计数变为零,那么运行时就可以立即收回这个块(并且减少被回收的块所引用的所有块的引用计数),或者将它放到迟延收集队列中。 许多 ANSI C++ 库类,比如 JDK 中的标准垃圾收集器都没有使用引用计数,相反,它们都使用某种形式的 跟踪收集器 (tracing collector)。跟踪收集器停止所有工作(尽管不需要在收集的整个过程中都这样)并开始跟踪对象,从根集开始沿着引用跟踪,直到检查了所有可到达的对象。可以在程序注册表中、每一个线程堆栈中的(基于堆栈的)局部变量中以及静态变量中找到根。 最早由 Lisp 的发明人 John McCarthy 于 1960 年提出的最基本的跟踪收集器形式是 标记―清除收集器,它停止所有工作,收集器从根开始访问每一个活跃的节点,标记它所访问的每一个节点。走过所有引用后,收集就完成了,然后就对堆进行清除(即对堆中的每一个对象进行检查),所有没有标记的对象都作为垃圾回收并返回空闲列表。图 1 展示了垃圾收集之前的堆,阴影块是垃圾,因为用户程序不能到达它们: 标记-清除实现起来很简单,可以容易地回收循环的结构,并且不像引用计数那样增加编译器或者赋值函数的负担。但是它也有不足 ―― 收集暂停可能会很长,在清除阶段整个堆都是可访问的,这对于可能有页面交换的堆的虚拟内存系统有非常负面的性能影响。 标记-清除的最大问题是,每一个活跃的(即已分配的)对象,不管是不是可到达的,在清除阶段都是可以访问的。因为很多对象都可能成为垃圾,这意思着收集器花费大量精力去检查并处理垃圾。标记-清除收集器还容易使堆产生碎片,这会产生区域性问题并可以造成分配失败,即使看来有足够的自由内存可用。 在另一种形式的跟踪收集器 ―― 复制收集器中,堆被分成两个大小相等的半空间,其中一个包含活跃的数据,另一个未使用。当活跃的空间占满以后,程序就会停止,活跃的对象被从活跃的空间复制到不活跃的空间中。空间的角色就会转换,原来不活跃的空间成为了新的活跃空间。 复制收集的优点是只访问活跃的对象,这意味着不会检查垃圾对象,也不需要将它们页交换到内存中或者送到缓存中。复制收集器的收集周期时间是由活跃对象的数量决定的。不过,复制收集器因为要将数据从一个空间复制到另一个空间、调整所有引用以指向新备份而增加了成本。特别是,长寿的对象在每次收集时都要来回复制。 复制收集器有另一个好处,活跃对象集会被整理到堆的底部。这不仅改进了用户程序的引用区域性并消除了堆碎片,而且极大地减少了对象分配的成本 ―― 对象分配变成了在堆顶部的指针上增加指针。不需要维护自由列表或者后备列表,或者使用性能最佳或者第一合适的算法 ―― 分配 为非垃圾收集语言实现了复杂内存管理方案的开发人员可能会对复制收集器中廉价的内存分配感到吃惊 ―― 就是指针加法这么简单。以前的 JVM 实现没有使用复制收集器 ―― 这可能是对象分配是昂贵的这一想法是如此普遍的原因之一,开发人员仍然下意识地假设分配成本与其他语言(如 C)类似,而事实上在 Java 运行时中可能要廉价得多。不但是分配成本减少了,而且对于在下次收集之前成为垃圾的对象,解除分配的成本为零,因为既不会访问也不会复制垃圾对象。 复制算法的性能很优异,但是它有一个缺点是需要两倍于标记-清除收集器所需要的内存。 标记-整理 算法结合了标记-清除和复制,避免了这个问题,代价是增加了一些收集复杂性。与标记-清除类似,标记-整理是两阶段过程,在标记阶段访问并标记每个活跃对象。然后,复制标记的对象,使所有活跃对象被整理到堆的底部。如果每一次收集时进行彻底的整理,那么得到的堆就类似于复制收集器的结果 ―― 在堆的活跃部分与自由部分有明确的界线,这样分配成本与复制收集器相当。长寿的对象趋向于沉在堆的底部,这样就不会像在复制收集器中那样反复复制它们。 那么 JDK 使用了哪种方式进行垃圾收集呢?在某种意义上,使用了所有的方式。早期的 JDK 使用了单线程的标记-清除或者标记-清除-整理收集器。1.2 及以后的 JDK 使用了混合的方式,称为 分代收集,其中根据对象的年龄将堆分为几个部分,不同的代是用不同的收集算法收集的。 分代收集证明是非常高效的,尽管在运行时它需要更多的簿记。在下一个月的 Java 理论与实践 中,除了介绍 1.4.1 JVM 提供的所有其他垃圾收集选项之外,我们还将探讨分代收集是如何工作的以及 1.4.1 JVM 是如何使用它的。在下下篇文章中,我们将分析垃圾收集对性能的影响,包括揭示与内存管理有关的性能神话。 出处:developerWorks
string
,使用了引用计数来提供垃圾收集的特性。通过重载赋值操作符并利用 C++ 作用域提供的确定性结束,C++ 程序可以将 string
类当成是被收集的垃圾那样使用。引用计数很简单,很适用于增量收集,收集过程一般会得到好的引用区域性,但是出于几个理由,它很少在生产垃圾收集器中使用,如它不能回收不可到达的循环结构(彼此直接或者间接引用的几个对象,如循环链接的列表或者包含指向父节点的反向指针的树)。
图 1. 可到达和不可到达的对象
N
字节就是在堆顶部指针上加 N
并返回前一个值这么简单,如清单 1 所示:
清单 1. 复制收集器中廉价的内存分配
void *malloc(int n) {
if (heapTop - heapStart < n)
doGarbageCollection();
void *wasStart = heapStart;
heapStart += n;
return wasStart;
}
发表评论
-
.NET开源核心运行时,且行且珍惜
2014-12-25 15:39 1869背景 2014年11月12日,ASP.NET之父、微软云 ... -
常用 Java Profiling 工具的分析与比较
2010-08-15 22:04 1203相对于静态代码分析,Profiling 是通过收集程序运行 ... -
监控系统内存
2010-07-01 14:15 1217public CollectorThread(int seco ... -
Debugging the JNI
2010-06-18 14:03 1003If you think you have a JNI p ... -
JNI原理2
2010-06-18 13:31 162115.2 调用C程序 JNI规范 ... -
JNI原理1
2010-06-18 13:14 1263在某些Java的忠实支持者眼中,JNI(Java Nati ... -
JNI的crash终于搞定<转>
2010-06-18 13:08 1678今天终于搞定困扰我一周的一个问题了。我们的算法通过jni封装, ... -
java的volatile是什么意思
2010-04-20 15:39 1338我们知道,在Java中设置变量值的操作,除了long和d ... -
Concurrent kickoff
2010-04-19 15:55 1390This example shows you the ... -
IBM JDK和sun jdk区别
2010-04-19 15:52 2592在IBM的虚拟机官方指导文档中明确指出,禁止将虚拟机的最大 ... -
如何在IBM JDK 1.4.2的环境中避免Java堆空间的碎片问题
2010-04-19 15:48 880用户在使用WebSphere Applic ... -
Concurrent mark
2010-04-15 19:39 1023Concurrent mark gives reduced ... -
Java 技术,IBM 风格: 垃圾收集策略,第 1 部分
2010-04-15 16:51 1005可以使用 4 种不同的策略配置 IBM Developer ... -
Java 网页浏览器组件介绍
2010-04-12 23:44 1506前言 在使用 Java 开发客户端程序时,有时会需要在界 ... -
利用 Java dump 进行 JVM 故障诊断
2010-04-06 16:54 1987引言 对于大型 java 应用程序来说,再精细的测试都难 ... -
IBM JVM垃圾回收原理——1
2010-04-06 15:42 1621原文下载:IBM Garbage Collection ... -
关注性能: 调优垃圾收集
2010-04-06 14:08 843随着网志作为公共日 ... -
Java 理论与实践: JVM 1.4.1 中的垃圾收集
2010-04-06 10:42 899老对象和年轻对象 ... -
优化 Java 垃圾收集器改进系统性能
2010-04-02 16:05 924From http://www.ibm.com/de ... -
搞懂java中的synchronized关键字
2010-04-01 19:54 816实际上,我关于java的基 ...
相关推荐
互联网治理简史 互联网的诞生和发展是一系列的创新、普及和管理事件的结果。在20世纪,互联网的萌芽时期,科技进步为互联网的诞生奠定了基础。例如,1946年,世界上第一台通用计算机ENIAC的诞生标志着计算机技术的...
东方证券_0518_金工磨刀石系列之四:英国市场简史与现状.pdf
从愚昧到科学:科学技术简史七到十二章.doc
JAVA内存模型与垃圾回收是Java开发中至关重要的概念,它们直接影响到程序的性能和稳定性。首先,我们来看看Java内存模型。 Java内存模型,通常被称为JVM内存模型,它定义了程序中不同部分如何访问和共享数据。在...
读《世界是平的:21世纪简史》有感归纳.pdf
从“愚昧”到科学:科学技术简史七到十二章.doc
专题报告:REITs发展国际经验系列:美国REITs简史(2022)(18页).pdf
2018年从“愚昧”到“科学”:科学技术简史课后习题答案.doc
5. 人工智能的行业应用:书中通过理论与案例的结合,全方位解析了人工智能在20多个行业的70多种产品中的应用。这些行业涵盖了工业检查、工业生产、工业设计、陶瓷工业、交通安防等,显示了人工智能技术的广泛渗透和...
《从“愚昧”到“科学”:科学技术简史》期末考试答案涵盖了多个科学和技术领域的重要知识点,让我们逐一解析。 1. **中国古代科技**:中国古代的青铜镜制作技术可追溯到4000年前,展示了古代中国在金属冶炼方面的...
《从“愚昧”到“科学”:科学技术简史》是一门探讨科学技术发展历程的课程,旨在深入了解科学的本质、科学史的重要人物以及学习科学史的意义。本课程覆盖了多个主题,如科学和科学史的定义、科学史的奠基人萨顿的...
13. 科学系统化:萨顿认为科学系统化和理论化是在古希腊时期开始的。 14. 俄罗斯科学院研究方向:化学不在初期的三级研究方向之列,它们可能是数学、物理学和人文科学。 15. 射线的发现:贝克勒耳发现射线是因为...
#### 二、在线广告简史 ##### 1. 世界上第一个在线广告——AT&T的Banner广告 1994年10月27日,AT&T以CPD(Cost Per Day)的形式在HotWired.com上投放了首个在线Banner广告,标志着互联网广告时代的开启。该广告点击率...
1、Java语言发展简史 2、Java语言特性 3、Java程序运行机制 4、SDK的下载安装及环境变量配置 5、第一个手写java程序 6、如何在dos下手动运行 7、eclipse的下载安装及环境变量配置 8、第一个eclipse编写的java程序
《诗词创作理论与实践》课程大纲 一、课程概述 《诗词创作理论与实践》是一门融合文学理论与创作实践的创新学分课程,旨在培养学生的诗词创作能力,深化对中国传统文化的理解,以及提升审美素养。课程通过理论讲解...
电磁理论的发展简史: 电磁理论是一门研究电荷、电流产生的电场和磁场,以及它们之间相互作用的科学。它的起源可以追溯到古希腊时期,当时人们发现了磁石吸铁的性质以及琥珀经过摩擦之后可以吸引轻小物体的现象。...