代
J2SE平台的一个优点是它可以保护开发人员免受内存分配和垃圾收集的复杂性。但是,一旦垃圾收集成为主要瓶颈,就值得了解这个隐藏实现的某些方面。垃圾收集器对应用程序使用对象的方式做出假设,这些可以反映在可调参数中,可以调整这些参数以提高性能,而不会牺牲抽象的功能。
当一个对象无法再从正在运行的程序中的任何指针到达时,它被认为是垃圾。最简单的垃圾收集算法简单地遍历每个可到达的对象。剩下的任何对象都被认为是垃圾。这种方法所花费的时间与活动对象的数量成正比,这对于维护大量实时数据的大型应用程序来说是不可行的。
从J2SE平台版本1.2开始,虚拟机包含许多不同的垃圾收集算法,这些算法使用分代集合进行组合 。虽然天真的垃圾收集检查堆中的每个活动对象,但是分代收集利用了大多数应用程序的几个经验观察的属性以避免额外的工作。
这些观察到的特性中最重要的是 对象死亡率。 例如,迭代器对象在单个循环的持续时间内通常是活动的。
有些物体的寿命更长,因此分布延伸到右侧。例如,通常在初始化时分配一些对象,这些对象一直存在直到进程退出。在这两个极端之间是在一些中间计算期间存活的物体,在这里看作是对象死亡率峰值的右侧。一些应用具有非常不同的外观分布,但是令人惊讶的大量具有这种一般形状。通过关注大多数物体“年轻”的事实,可以实现高效的收集。
为了优化这种情况,内存是在几代中管理的 ,或者内存池包含不同年龄的对象。当生成填满时,每一代都会发生垃圾收集。物体被分配在一代中用于较年轻的物体或 年轻一代,并且由于对象死亡,大多数物体死在那里。当 年轻一代填满它会导致一个 小的收集。假设对象死亡率很高,可以优化次要收集。这些集合的成本,就第一顺序而言,与收集的活动对象的数量成比例。一个 年轻人很快收集到充满死亡物体的一代。一些幸存的物体被移动到 终身一代。当 需要收集终生代时,有一个 主要集合通常要慢得多,因为它涉及所有活动对象。
下框显示 了以足够长的间隔发生的次要集合,以允许许多对象在集合之间死亡。从年轻一代足够大(因此在次要收集之间的时间足够长)的意义上来说,它是经过精心调整的 ,因为次要收集可以利用高对象死亡率。具有不寻常的生命周期分布的应用程序或者在对象有时间死亡之前导致集合发生的大小不足的代数可能会扰乱这种情况。
如第2部分所述,人体工程学nows对垃圾收集器做出了不同的选择,以便在各种应用中提供良好的性能。串行垃圾收集器旨在供小型应用程序使用。其默认参数设计为对大多数小型应用程序有效。吞吐量垃圾收集器旨在供大型应用程序使用。由人体工程学选择的堆大小参数加上自适应大小策略的功能旨在为服务器应用程序提供良好的性能。这些选择适用于许多应用程序,但并不总是有效。这导致了本文件的核心原则:
如果垃圾收集器已成为瓶颈,您可能希望自定义生成大小。检查详细的垃圾收集器输出,然后探索各个性能指标对垃圾收集器参数的敏感性。
代数的默认排列(对于除吞吐量收集器之外的所有收集器)看起来像这样
在初始化时,除非需要,否则实际上保留了最大地址空间但未分配给物理内存。为对象存储器保留的完整地址空间可以分为 年轻和 终生代。
在 年轻一代包括 伊甸加上两个 幸存者空间。对象最初在eden中分配。一个 幸存者空间在任何时候都是空的,并且作为下一个的目的地,复制伊甸园和其他幸存者空间中任何活物的集合。以这种方式在幸存者空间之间复制对象,直到它们足够老到终身,或者复制到 终身代。
其他虚拟机,包括用于Solaris操作系统的J2SE平台1.2版的生产虚拟机,使用两个大小相等的空间进行复制,而不是使用一个大的eden加上两个小空间。这意味着衡量 年轻一代的选择不具有直接可比性
与终身一代密切相关的第三代 是 永久性的一代。该 永久代是特殊的,因为它拥有由虚拟机来形容那些没有在Java语言水平的等价物所需要的数据。例如,描述类和方法的对象存储在 永久代中。
有点像常说的方法区》 永久代
调整世代
许多参数会影响生成大小。堆中的已提交空间和虚拟空间之间的区别:
在初始化虚拟机时,将保留堆的整个空间。可以使用-Xmx选项指定保留空间的大小。如果-Xms参数的值小于-Xmx参数的值,则不会立即将所有保留的空间提交给虚拟机。未提交的空间标记为“虚拟”。堆的不同部分( 永久生成, 终身生成和 年轻生成)可以根据需要增长到虚拟空间的限制。
一些参数是堆的一部分与另一部分的比率。例如,参数NewRatio表示终生代与 年轻代的相对大小 。这些参数将在下面讨论。
关于堆的增长和收缩的以下讨论不适用于吞吐量收集器。
总堆
由于收集发生在代数填满时,吞吐量与可用内存量成反比。可用内存总量是影响垃圾收集性能的最重要因素。
默认情况下,虚拟机会在每个集合中增大或缩小堆,以尝试将可用空间的比例保持为特定范围内每个集合的活动对象。此目标范围通过参数-XX:MinHeapFreeRatio =
-XX:MinHeapFreeRatio =
40
-XX:MaxHeapFreeRatio =
70
-Xms
3670k
-Xmx
64m
64位系统上堆大小参数的默认值已按比例放大约30%。此增加旨在补偿64位系统上较大的对象大小。
使用这些参数,如果一代中的自由空间百分比低于40%,则生成的大小将扩大,以便有40%的空间可用,假设生成的大小尚未达到其极限。类似地,如果自由空间的百分比超过70%,则生成的大小将缩小,以便只有70%的空间可用,只要缩小生成不会使其低于生成的最小大小。
大型服务器应用程序经常遇到这些默认值的两个问题。一个是慢启动,因为初始堆很小,必须在许多主要集合上调整大小 。一个更紧迫的问题是,对于大多数服务器应用程序,默认的最大堆大小是不合理的小。服务器应用程序的经验法则是:
除非您遇到暂停问题,否则请尽量为虚拟机授予尽可能多的内存。默认大小(64MB)通常太小。
将-Xms和-Xmx设置为相同的值可通过从虚拟机中删除最重要的大小决策来提高可预测性。另一方面,如果做出糟糕的选择,虚拟机无法补偿。
确保在增加处理器数量时增加内存,因为分配可以并行化。
年轻一代
第二个最有影响力的旋钮是专用于年轻一代的堆的比例 。年轻一代越大 ,次要收藏品就越少。然而,对于有限的堆大小,较大的 年轻一代意味着较小的 终生代,这将增加主要集合的频率。最佳选择取决于应用程序分配的对象的生命周期分布。
默认情况下, 年轻一代的大小由NewRatio控制。例如,设置-XX:NewRatio = 3意味着年轻和 终生代之间的比例 是1:3。换句话说,伊甸园和幸存者空间的组合大小将是总堆大小的四分之一。
NewSize和MaxNewSize参数限制了 年轻一代的大小。将这些设置为彼此相等可以修复 年轻代,就像设置-Xms和-Xmx等于修复总堆大小一样。这对于以比NewRatio允许的整数倍更精细的粒度调整年轻代有用 。
年轻一代保证
在一个理想的次要收集的活动对象是从的一个部分复制 的年轻一代(伊甸园空间加上第一个生存空间)到另一部分 年轻一代(第二生存空间)。但是,无法保证所有活动对象都适合第二个幸存者空间。为了确保即使所有对象都处于活动状态也可以完成次要集合,必须在终身代中保留足够的可用内存 以容纳所有活动对象。在最坏的情况下,这个保留的内存等于伊甸园的大小加上非空幸存者空间中的对象。当终身没有足够的可用内存时 对于这种最坏的情况,将会出现一个主要的集合。此策略适用于小型应用程序,因为在tenured generation中保留的内存 通常只是虚拟提交但实际上没有使用。但是对于需要尽可能大堆的应用程序,大于堆的虚拟承诺大小的一半的eden是无用的:只会发生主要集合。请注意, 年轻代保证仅适用于串行收集器。吞吐量收集器和并发收集器将继续进行 年轻代收集,并且如果 终身代不能容纳来自的所有促销 年轻一代,两代人都被收集起来。
如果需要,参数SurvivorRatio可用于调整幸存者空间的大小,但这通常对性能不那么重要。例如,-XX:SurvivorRatio = 6将每个幸存者空间与伊甸园之间的比率设置为1:6。换句话说,每个幸存者空间将是年轻一代的八分之一 (不是七分之一,因为有两个幸存者空间)。
如果幸存者空间太小,则复制集合会直接溢出到 终身代。如果幸存者空间太大,它们将毫无用处。在每次垃圾收集时,虚拟机选择一个阈值次数,可以在对象被终止之前复制该对象。选择此阈值是为了使幸存者保持半满。选项-XX:+ PrintTenuringDistribution可用于显示此阈值和新一代中对象的年龄。它对于观察应用程序的生命周期分布也很有用。
以下是32位Solaris操作系统(SPARC Platform Edition)的默认值:
NewRatio
2 (客户端JVM:8)
新尺寸
2228k
MaxNewSize
不限
SurvivorRatio
32
所述的最大尺寸 年轻一代将从总堆和NewRatio的最大大小来计算。MaxNewSize的“不受限制”默认值意味着计算值不受MaxNewSize限制,除非在命令行上指定了MaxNewSize的值。
服务器应用程序的经验法则是:
首先确定您可以为虚拟机提供的内存总量。然后根据年轻代尺寸绘制您自己的性能指标, 以找到最佳设置。
除非您发现过多的主要收集或暂停时间的问题,否则给年轻一代留下足够的记忆 。
增加 年轻一代会在总堆积的一半或更少的时候适得其反(每当 年轻一代保证无法满足时)。
因为增加了处理器的数量,所以一定要增加 年轻代,因为分配可以并行化。
先看张图:
小总结 下哇:
堆最大内存是整个内存的4/1
堆最新64/1
年轻代占整个堆4/1
终生代占整个堆4/3
伊甸园占年轻代8/6
幸存区占年轻代8/1
64位 ,32位看上边
具体的垃圾收集器选择:根据项目类型:选择回收期
分代复制收集器:串行收集器,通过检查标签方式,只做复制不做任何回收
并行年轻代收集器:并行,多线程执行检测对象状态和对象复制
旧物件收集器:通过压缩死掉的对象到碎片,然后清理碎片
并行老年代收集器:通过在暂停时间,调用多个线程执行回收完成
---------------------
作者:a_Ygygs_Dxdsr_XdMss
来源:CSDN
原文:https://blog.csdn.net/weixin_42749765/article/details/87458803
版权声明:本文为博主原创文章,转载请附上博文链接!