在J2SE 5.0,垃圾收集的默认值:垃圾收集器、堆大小以及JVM的类型(客户端还是服务器)都会根据应用运行的硬件平台和操作系统自动选择。相比之前设置命令行参数的方式,自动选择很好的匹配了不同类型的应用系统。

另外,并行收集器增加了一种新的动态优化收集算法。在这种方法中,用户指定渴望的行为,垃圾收集器动态的调整堆区域的大小力图实现所需的行为。依赖于平台的默认选择和垃圾收集器自动调整所需的行为称谓工效学。工效学的目标是提供很好的性能,同时只需要很少的命令行参数优化。

自动选择收集器、堆大小和VM类型
拥有下面特性的认为是服务器类型的机器

  • 2个或更多的物理CPU,并且
  • 2G或更多的物理内存

这个服务器类型机器的定义适用于除了运行windwos操作系统的32位平台外的所有平台。
一个机器如果不是服务器类型的,默认的设置是:

  • client类型的JVM
  • 串行收集器(serial garbage collector)
  • 初始4M的堆
  • 最大64M的堆

在服务器类型的机器上,JVM通常都是server JVM,除非你显示的指定-client参数。运行server JVM的服务器类型的机器默认的收集器是并行收集器(parallel collector),否则默认是串行收集器。使用平行收集器在服务器类型机器上运行的JVM(client或者server),默认的初始和最大堆如下:

  • 初始堆是1/64的物理内存,最大1GB。
    (注意:最小初始值是32MB,因为服务器类型的机器至少拥有2GB内存,它的1/64是32MB)
  • 最大堆是1/4的物理内存,最大1GB

除此之外,非服务器级的机器使用相同的默认大小(4MB初始大小,最大64MB)。默认值通常可以用命令行参数改写。有关的参数在第八章给出。

基于行为的并行收集器优化
在J2SE 5.0中,并行收集器加入了一种新的基于应用系统期望垃圾收集行为的优化方法。
命令行参数用于指定最大暂停时间和应用程序吞吐量所期望的行为。

最大暂停时间目标
最大暂停时间目标通过如下参数指定:

引用:

-XX:MaxGCPauseMillis=n

这应解读为对于平行收集器的一个提示,期望暂停时间是n毫秒或者更少。并行收集器调整堆大小和其他垃圾收集器相关的参数力图保持垃圾收集暂停时间短于n毫秒。这些调整可能导致垃圾收集器降低整体应用的吞吐量,有时期望的暂停时间也实现不了。最大暂停时间目标分别应用在每个代。特别的,如果目标没达到,会减少代的大小尝试实现目标。默认情况下没有最大暂停时间的设置。

吞吐量目标
吞吐量目标在垃圾收集消耗的时间和非垃圾收集消耗的时间(归为应用时间)方面进行测量。这个目标通过如下参数指定:

引用:

-XX:GCTimeRatio=n

垃圾收集时间与应用时间的比例是

引用:

1 / (1 +  n)

例如 -XX:GCTimeRatio=19 设置了一个垃圾收集占总时间5%的目标。默认的目标是1%(即n=99)。垃圾收集花费的时间是所有代的总和。如果吞吐量目标没有达到,会增加代的大小以便让应用系统在两次垃圾收集之间可以运行的时间更长。大的代需要更长的时间填满。

占用空间目标
如果吞吐量目标和最大暂停时间目标实现了,垃圾收集器会减少堆的大小直到其中之一(总是吞吐量目标)不能实现。然后解决没满足的目标。

目标的优先级
并行收集器优先努力实现最大暂停时间目标。只有当这个目标达到后才解决吞吐量目标。同样的,在前两个目标达成后才会关心占用空间目标。


第六章 推荐

在上一章描述的工效学引导的自动的垃圾收集器、虚拟机、和堆大小的选择对于很大一部分的应用是合理的。因此,选择和配置垃圾收集器的初次推荐是什么都不做!就是说,不用指定特别的垃圾收集器,以及其他。让系统基于应用运行的平台和操作系统自动选择。然后测试你的应用。如果性能是可接受的,也就是拥有足够的吞吐量和足够短的暂停时间,你的事就做完了。你不需要排查故障或者更改垃圾收集设置。

另一方面,如果你的应用似乎存在垃圾收集相关的性能问题,最简单的你首先要做的是依据应用程序和平台特性想想默认选择哪个垃圾收集器。或者,先选择一个,然后看看性能是否能接受。

你可以用第七章描述的那些工具测量和分析性能。基于测量结果,考虑修改参数,比如堆大小或者垃圾收集行为。第八章列出了一些常用的命令行参数。注意:最好的性能优化方法是先测量,后调整。使用与你的代码真实运行相关的测试进行测量。并且,防止过度优化,因为应用程序的数据集,硬件,等等–甚至垃圾收集实现!–可能会随时间改变。
这一章提供了选择垃圾收集器和设置堆大小的信息。然后提供了一些优化并行垃圾收集器的建议,然后给出了关于OutOfMemoryError的处理建议。

选择一个不同的垃圾收集器

第四章说到对于每个收集器建议使用的场景。第五章描述了什么样的平台默认会自动选择串行或并行收集器。如果你的应用程序或环境特性期望一个相比默认不同的垃圾收集器,通过下面命令行参数明确的指定它:

复制内容到剪贴板

代码:

–XX:+UseSerialGC
–XX:+UseParallelGC
–XX:+UseParallelOldGC
–XX:+UseConcMarkSweepGC

堆大小

第五章说明了默认的初始和最大堆大小。这些大小对于大部分应用来说是何时的,但是如果你正在分析的性能问题(参见第七章)或者是OutOfMemoryError(本章后面会讨论)表明某个代或整个堆的大小存在问题,你可以通过第八章指定的命令行参数调整这些大小。例如,在非服务器类型的机器上,默认的最大堆大小64MB通常太小了,你可以通过-Xmx参数指定一个更大的。除非你遇到了长暂停时间的问题,否则应分配尽可能多的内存到堆。吞吐量与可用内存成比例变化。拥有足够的内存是影响垃圾收集性能最重要的因素。

决定总共分配多少内存给整个堆后你可以考虑每个代的大小。第二重要影响垃圾收集性能是的分配给年轻代的比例。除非你发现过多的年老代收集或暂停时间,应分配足够多的内存给年轻代。然而,如果你使用的是串行收集器,不要分配多余一半的堆内存到年轻代。

当你使用某种并行收集器时,优先指定期望的行为,而不是确切的堆大小值。然后让收集器自动动态的调整堆大小以便实现这些行为,下面会讲到。

并行收集器的优化策略

如果垃圾收集器选择(自动或明确指定)一个并行收集器或并行压缩收集器,然后指定一个吞吐量目标(参见第五章),通常对于你的应用程序就足够了。不要指定堆的最大值,除非你明确的知道需要的堆大小比默认要大。堆会自动增长或收缩到一定大小以支持选定的吞吐量目标。可以预期,在堆初始化和应用程序行为发生变化时可能发生一些堆大小的震荡。
如果堆大小增长到最大值,在大部分情况下这意味着基于这个最大值吞吐量目标无法达到。设置最大堆内存到接近物理内存并且不会导致交换应用程序的值。再次执行应用程序。如果吞吐量目标依然没有达到,则说明对于在这个平台上可用的内存来讲设置的目标太高了。

如果吞吐量目标可以达到,但是暂停时间太长,选择一个最大暂停时间目标。选择最大暂停时间目标可能意味着吞吐量目标达不到,所以要选择一个可接受的妥协的值。

垃圾收集器在满足互相矛盾的目标时可能导致堆大小来回震荡,直到应用程序达到一个稳定状态。迫使满足吞吐量目标(它需要大堆)与最大暂停时间目标和最小占用目标(这两个目标需要更小的堆)相矛盾。

遇到OutOfMemoryError时做什么

应用程序终端显示的java.lang.OutOfMemoryError是很多程序员都需要解决的通用问题。这个错误在没有空间分配对象时抛出。意思是,垃圾收集器不能再制造一些空间来容纳一个新对象,并且堆空间不能再扩展。OutOfMemoryError错误不一定意味着内存泄露。它可能是一个简单的配置错误,例如为应用程序配置不足的内存(或默认值没有设置)。
诊断OutOfMemoryError错误的第一步是检查完整的错误信息。在异常信息中,补充信息在“java.lang.OutOfMemoryError”之后提供。这里提供一些常见的可能的补充信息,以及他们是什么意思,针对他们该做些什么。

Java heap space

这表明对象不能在堆中分配。这个问题可能仅仅是一个配置问题。例如,通过命令行参数-Xmx指定的(或者默认的)最大堆内存对于应用来讲是不够的,你就会遇到这个错误。它也可能是一种迹象,不再需要的对象由于应用程序无意的引用着而不能被垃圾收集器回收。HAT工具(参见第七章)可以用来查看所有可引用到的对象,以及理解这些对象是如何被引用的。另一个可能导致这个错误的原因可能是应用过多的使用终结器(finalizers)以至于执行终结的线程跟不上加入终结队列的速度。jconsole管理工具可以用来监测等待终结的对象数量。

PermGen space

这表明持久代满了。如前所述,这个区域是JVM用来存放元数据信息的。如果应用程序加载了大量的类,则需要增加持久代大小。你可以通过这个命令行参数–XX:MaxPermSize=n实现,这里的n指大小。

Requested array size exceeds VM limit

这表明应用程序企图分配的数组比堆还大。例如,应用程序尝试分配一个512MB的数组,但是堆最大才256MB,就会出现这个错误。大部分情况下,这个错误要不就是因为堆太小,要不就是因为应用程序计算数组的大小时发生错误引起了一个bug。

一些在第七章描述的工具可以被用于诊断OutOfMemoryError问题。最有用的一些工具室Heap Analysis Tool(HAT)、jconsole管理工具、附加-histo参数的jmap工具。

【摘录】JAVA内存管理-自动选择垃圾收集器算法的更多相关文章

  1. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  2. Java内存管理-掌握虚拟机类加载器(五)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍虚拟机类加载机制,讲解了类加载机制中的三个阶段,分别是:加载.连接(验证.准 ...

  3. Java内存管理-掌握自定义类加载器的实现(七)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分析了ClassLoader的类加载相关的核心源码,也简单介绍了ClassLoa ...

  4. java 内存管理 —— 《Hotspot内存管理白皮书》

    说明   要学习Java或者任意一门技术,我觉得最好的是从官网的资料开始学习.官网所给出的资料总是最权威最知道来龙去脉的.而Java中间,垃圾回收与内存管理是Java中非常重要的一部分.<Hot ...

  5. 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.3.垃圾收集器与内存分配策略

    1.学习目的 当需要排查各种内存溢出. 内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. Java内存运行时区域的各个部分,其中程序计数 ...

  6. 【摘录】JAVA内存管理-有关垃圾收集的关键参数

    第八章 有关垃圾收集的关键参数 一些命令行参数可以用来选择垃圾收集器,指定堆或代的大小,修改垃圾收集行为,获取垃圾收集统计数据.本章给出一些最常用的参数.有关各种各样参数更多完整的列表和详细信息可以参 ...

  7. java内存管理(堆、栈、方法区)

    java内存管理 简介 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们释放了内存了吗?但是在写程序的过程中却也往往因为不懂内存管理而造成了一些不容易察觉 ...

  8. Java内存管理及对Java对象管理

    Java内存管理及对Java对象管理 1Java内存管理 1.1Java中的堆和栈 通常来说,人们会将Java内存氛围栈内存(Stack)和堆内存(Heap). 栈内存用来保存基本类型的变量和对象的引 ...

  9. 揭开Java内存管理的面纱

    前言 相对于C.C++这些高性能语言,Java有着让此类程序员羡慕的功能:内存自动管理.似乎这样,Java程序员不用再关心内存,也不用去了解相关知识.但结果真的是这样吗?特别对于我们这种Android ...

随机推荐

  1. mindmanager 2018 中文破解版_注册码_免激活

    MindManager 2018是一个可视化的工具,可以用在脑力风暴(brainstorm)和计划(plan)当中.为商务人士提供更有效的.电子化手段捕捉.组织和联系信息(information)和想 ...

  2. hibernate增删改查总结

    hibernate操作的都是基于对象的(曾save删delete改update) 进行hql查询是设置参数从零开始(session.setParameter(0,#)) hql查询设置参数可以是其他( ...

  3. Windows Server菜鸟宝典之一:Windows Server 2008 R2 AD服务器搭建

        1.对于将要安装成为DC的服务器来讲,其系统配置以及基本的磁盘规划在此就不在累述了,但是关键的网络连接属性是必须要注意的.可以通过打开本地连接的属性来进行配置其IP属性.作为服务器DC的IP地 ...

  4. VS2013 opencv 无法删除“继承的值”问题解决方案

    http://www.360doc.com/content/15/0103/14/110467_437739376.shtml 解决方案: (1)视图——其他窗口——属性管理器. 注意:是”属性管理器 ...

  5. vue的计算属性get和set

    1.计算属性是用来存储数据,但具有以下几个特点: a.数据可以进行逻辑处理操作. b.对计算属性中的数据进行监视. 2.计算属性和普通属性的区别: a.计算属性是基于它的依赖进行更新的,只有在相关依赖 ...

  6. 用SufaceGO加微软全家桶做个遥控车(一)

    作为一个dotnet技术的新手我是不好意思写帖子的,原因就是本人技术太水了,写出的帖子肯定会让人笑话.所以这次我是厚着脸皮写出这个帖子的,希望大佬们轻喷了.我的目标就是用SurfaceGo实现一个和我 ...

  7. 【JavaScript框架封装】实现一个类似于JQuery的事件框架的封装

    // 事件框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 实现一个浏览器的基本 ...

  8. Java工具类使用注意事项

    (以下摘自阿里巴巴Java开发手册) 1. [强制]获取单例对象需要保证线程安全,其中的方法也要保证线程安全. 说明:资源驱动类.工具类.单例工厂类都需要注意. 5. [强制]SimpleDateFo ...

  9. js中Number()、parseInt()和parseFloat()的区别进行详细介绍

    http://www.jb51.net/article/100606.htm 区别: parseFloat,parseInt  解析的过程中如果前面有空格,结果不会有任何影响,Number解析的时候结 ...

  10. 关系数据库标准语言SQL

    篇幅过长,恐惧者慎入!!!基础知识,大神请绕道!!! 本节要点: l  SQL概述 l  学生-课程关系 l  数据定义 基本表的定义.删除与修改 索引的建立与删除 l  查询 单表查询 连接查询 嵌 ...