没有合适的资源?快使用搜索试试~ 我知道了~
JAVA虚拟机的内存管理
需积分: 9 3 下载量 185 浏览量
2012-03-23
15:45:30
上传
评论
收藏 371KB PDF 举报
温馨提示
试读
21页
JAVA虚拟机的内存管理,详细讲解了JAVA虚拟机的相关配置
资源详情
资源评论
资源推荐
HotSpot JVM 的内存管理
1 引言(Introduction)
在强大的 Java™ 2 平台下,J2SE 可以自动的管理内存,所以将开发者从复杂的显性管
理内存的工作中解放出来。
本片文档是对 Sun J2SE 5.0 release 版本的 Java HotSpot JVM 内存管理机制的概述。描述
了可用于内存管理的几种内存收集器,以及给出了一些建议,例如,如何选择和配置内存收
集器、如何配置收集器内存区域的尺寸。也给出了一些资料,列出了一些影响内存收集器行
为的常用选项并且提供了大量有关于细节的文档链接。
Section 2 是写给那些刚刚接触自动内存管理的读者。其中有一个简短的讨论是与要求
程序员手动释放对象空间对比,自动内存管理机制可以获得的好处。
Section 3 概述了一些内存回收的基本概念、设计方案和
性能指标,并且介绍了“代”,
“代”是根据对象寿命将内存组织成了不同的区域。已经证明了这种组织方式可以在内存回
收中减少暂停时间和整理大区域的成本。
接下来的内容集中在了 HotSpot JVM 上。Section 4 描述了 4 种可以使用的内存收集器,
其中一种是在 J2SE 5.0 update 6 中引入的,还记录了他们使用的常见的内存组织形式。另外
Section 4 简单介绍了每种收集器的运行原理以及适合于哪种场景。
Section 5 描述一种在 J2SE 5.0 release 中的新技术,它可以根据应用运行的平台和操作
系统自动的选择内存收集器类型和堆尺寸以及工作模式(client or server); 还可以根据用户
期望的目标自动调节垃圾收集的参数,这个技术叫做工效学(ergonomics)。
Section 6 给出了一些关于如何选择和配置内存收集器的建议以及如何处理
OutOfMemoryError 异常的建议。Section 7 简单描述了一些可以用来评估内存收集表现的工
具,并且在 Section 8 中列出了与内存收集器的选项和行为相关的最常用的命令行参数。最
后 Section 9 给出了本文档提到的一些议题的更细节文档的链接。
2 手动 VS 自动内存管理(Explicit vs.
Automatic Memory Management
)
内存管理是下面的描述的过程。当已经分配过内存的对象不在被使用的时候需要释放它
所占用的内存并可以分配给接下来的申请者。这个过程在一些程序语言中是由程序员控制
的,然而在这种复杂的工作中经常会发生一些错误,这些错误会导致不可预计的行为或者直
接导致程序的崩溃,所以开发者的大量时间花费在调试和纠正这种错误上。
在手动内存管理的语言中经常遇到的问题就是悬挂引用(dangling refrences)。含义是一
个对象被其他对象引用着,但是它占用的内存却已经被释放掉了,那么如果引用者访问被引
用对象并且那个空间已经分配给了新的对象时,结果就是不可预知的。
手动管理内存的另一个常见问题是空间泄漏(space leaks)。这种泄漏发生在不能释放掉
已经分配但不再使用的内存。例如,当你释放链表的空间时,恰巧释放在第一个元素占用的
空间的时候发生了错误,那么链表中其他元素就不再被引用了,程序也无法引用他们,所以
它们既不能被使用也不能被覆盖。如果发生了很多这样的泄漏,那么所有的可用内存都可能
被消耗掉。
另一种管理内存的方法是自动管理,这种方法很常见,尤其是在现代的面向对象的语言
中。自动管理使用了一种叫做内存垃圾收集器(garbage collector)的程序。自动的内存管理
可以提高代码的抽象度和可靠性。
垃圾收集器避免了悬挂指针(dangling reference),原因是一个仍然被引用的对象永远不
会内存回收并且也不会被认为已经被释放掉了。垃圾收集器解决了空间泄漏(space leaks)
问题,原因是它可以自动释放不再被引用的空间。
3 内存收集的概念(Garbage Collection
Concepts
)
一个内存收集器具有下面的功能:
分配内存
保证所有被引用的对象还在内存中
可以释放在运行的代码中不再引用的对象的内存
如果对象被引用着,那我们说它活着(live);如果对象不再被引用了,那我们说他死了
(dead),术语称作垃圾(garbage)。寻找并释放这些对象的空间的过程就做垃圾收集(garbage
collection)。
垃圾收集解决了内存分配的很多问题但不是所有问题。例如,你可以无限期的创建对象
并保持对他们的引用,直到内存耗尽。垃圾收集本身也是一个复杂的工作,需要消耗时间和
资源。
垃圾收集器使用了一种精确的算法用于组织内存、分配与释放空间,并且这种算法对于
编程人员来说是透明的。被分配的空间来自于被称为堆(heap)的大块的内存池。
那么在什么时候会出发垃圾收集动作呢?一般来说整个堆或一部分被填满或者达到某
一百分比数值时将被收集。
为了满足一个内存分配的请求,必须要在堆中找到一块特定尺寸的没有被使用的内
存,然而这是一个艰难的任务。大多数动态内存分配算法的主要问题是避免碎片
(fragmentation),这样可以使内存的分配与释放更有效率。
理想的垃圾收集器的特点(Desirable Garbage Collector
Characteristics
)
一个垃圾收集器必须是即安全又足够聪明的。也就是说,存活的数据一定不能被释放掉,
并且垃圾对象应该在尽量少的收集周期中被释放掉。垃圾对象即使出现了一定规模的循环引
用也一定要释放掉。
理想的垃圾收集器的操作是非常高效的,不会引起长暂停(在这段时间里应用程序是无
法运行的)。尽管如此,像大多数与计算相关的系统一样,需要在时间、空间和频率保持平
衡。例如,如果堆比较小,那么垃圾收集会很快但是堆也会很快被填满,所以收集的频率会
更高。相反,一个大体积的堆需要花费更长的时间才能填满,所以会大大降低回收频率,但
是每次回收的时间会更长。
理想的垃圾收集器的另一个特点是对存储碎片的限制。当垃圾对象被释放时,释放的空
间将以小的字节形式存在于各个领域,因此,当为大的目标分配空间时,任何一个邻近领域
中的已释放空间都不够大。一种清除碎片的方法是压缩法(Compaction), 下节讲述设计选
择时将会详细介绍压缩法。
可收缩性(Scalability)也很重要。在多处理器系统中多线程应用上,分配空间不应该
成为可收缩性的瓶颈,并且收集也不应该成为一个瓶颈。
设计选择(Design Choices)
当设计或者选择垃圾收集器的算法时,需要做许多选择。
串行 VS.并行(Serial versus Parallel)
对于串行收集,一次只会有一件事会发生。例如,即使当多 CPU 体系可以应用时,只
有一个会被用来执行收集任务。当使用并行收集时,垃圾收集工作被分成几部分,这些子部
将会在不同的 CPU 上被同时执行。同时执行会使垃圾收集得更快,但是代价是会增加复杂
性和潜在碎片。
并发 VS. 完全停顿(Concurrent versus Stop-the-world)
当执行停顿垃圾收集(stop-the-world garbage collection)时,应用程序会被完全挂起。相反,
一个或者多个垃圾收集任务也可以并发的与应用程序同时执行。通常,一个并发收集器可以
并发的执行垃圾收集的大部分工作,但是也会不可避免的引发一个小的停顿。停顿垃圾收集
要比并行的垃圾收集器简单,因为收集期间的堆是冻结的,其中的对象不会发生变化;它 的
缺点是应用程序一定会发生停顿。相应的,如果并发的执行垃圾收集则暂停时间会更短,但
是内存收集器必须更加小心,因为在其工作期间一个对象可能已经被应用程序修改过了;这
种额外的负担影响了并发收集器的性能并且要求一个大尺寸的堆。
压缩 VS.非压缩 VS.拷贝
在垃圾收集器判断完存储器中有用的数据和垃圾数据后,垃圾收集器会压缩存储器,将
有用的数据移到一起,而剩下的存储空间被全部回收。压缩结束后,在释放的地址上分配一
个新的目标是非常简单快速的。可以用一个简单的指针指向下一个未分配的空间。与压缩收
搜集器相比,非压缩收集器用占位(in-place)垃圾目标来释放空间,与压缩收集器不同,非压
缩收集器不通过移动所有有用的数据来创造一个大的再回收空间。非压缩收集器的优点是可
以快速进行垃圾收集,缺点是存在潜在碎片。通常,用在适当位置(in-place)再分配一个堆比
用压缩法更为昂贵。在存储器邻近区域寻找一个有足够空间来分配新目标的堆是很有意义
的。第三个选择是拷贝收集器,它拷贝有用的数据到不同的存储地址。这样它的资源空间就
可以被认为是可分配的,并且可以快速容易的分配,但 是 拷贝收集器的缺点是需要拷贝数据
的额外的时间和空间。
性能指标
垃圾收集器的性能指标如下:
1. 吞吐量(Throughput):没有花费在垃圾回收的时间占总执行时间的百分比。
2. 逆吞吐量(Garbage collection overhead):垃圾收集的时间所占总执行时间的百分比。
3. 暂停时间(Pause time):当垃圾收集器执行时,应用程序停止运行的时间。
4. 收集频率(Frequency of collection):收集器工作的频度,与应用程序运行情况有关。
5. 印迹(Footprint):一种度量方式,就像堆的大小。
6. 及时性(Promptness):当一个目标变成垃圾后,多久这个存储空间会变成有用的。
一个交互式请求可能会要求低的暂停次数,然而总共的执行时间对于非交互式请求来说
更重要;一个实时的应用可能要求不能出现长时间的停顿又要平衡花费在垃圾收集的各个阶
段的时间;在小型个人微机或者嵌入系统中可能更加在意小的印迹。
世代收集器(Generational Collection)
使用世代收集器技术,存储器被分成几个代,就是用独立的池容纳不同年龄的目标。例
如,最广泛应用的方案有两个代:一个为新对象,一个为就对象。
不同的代可以用不同的算法来执行垃圾收集,每个算法根据不同代的不同测试结果进行
优化。世代收集器会开发如下的测试,被称作弱世代假说(Weak generational hypothesis),
相关的应用采用几种程序语言编写,包括 Java 程序语言:
1. 大多数分配目标长时间不被引用,也就是,它们夭折了。
2. 从老一代到新生代目标的引用很少存在。
新生代收集器的发生频率与效率都很高,因 为 新生代空间通常较小并且可能容纳许多不
再被引用的目标。
新生代收集器中存活的对象最终会进入旧生代,见图片 1。旧生代比新生代明显大,并
且内存的消耗速度更慢。结果,旧生代收集器很少执行,并且需要更长的时间来完成。
因为新生代发生垃圾收集的频度分厂高,所以在考虑为它选择收集算法的时候需要
特别考虑收集速度;另外,由于旧生代占用的堆空间是最大的并且必须在低垃圾密度下很好
的工作,所以它的算法更侧重与空间的使用效率。
4 在 J2SE 5.0 HotSpot虚拟机中的垃圾收集
器(Garbage Collectors in the J2SE 5.0
HotSpot JVM
)
The Java HotSpot virtual
J2SE 5.0 update 6 中 JVM 包含四种垃圾收集器,都是基于代的,本节描述了代与其他
类型的组合。并针对每个收集器为什么可以快速和有效的分配对象而给出了详细的资料。
HotSpot Generations
在 JVM 中内存被分为三代:新生代(Young Generation)、 旧生代(Old Generation)和
持久代(Permanent Generation)。 其 中 新生代一般用于放置新创建的对象,而旧生代则将一
些经过几次垃圾回收仍然没有被回收的对象转移存放进来。持久代用于放置一些为 JVM 本
身的方便性而使用的对象,比如类定义、方法定义、常量、代码段等。
新生代是由一个 Eden 区和两个 survivor 区组成。如图 2。大多数的对象是在 Eden 区生
成的,(正如上文所说,少数对象可能会直接分配到旧生代里)。当一个 survivor 区满时,有
些对象经过至少一个回收周期仍然未被回收将要进入旧生代之前,将被存放到另一个标记为
空的 survivor 区内,等待下一次的垃圾回收。
Garbage Collection Types(垃圾收集的类型)
当新生代满时,自身范围内会做一个代内收集(有时称为轻微收集)。当旧生代或者持
剩余20页未读,继续阅读
大鸟软件
- 粉丝: 6
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0