关于垃圾收集者,我们已经学到了很多东西。如果经常出现垃圾回收,或者占用时间太长的CPU时间,我们必须引起注意。这次,需要一些跟踪参数,以进一步确定垃圾回收器的效率和效果。我们需要学习输出并产生GC日志。本文基于JDK1.8+的想法,以帮助每个人输出并查看GC日志。
-XX:+PRINTGC输出简单的GC log -xx:+PRINTGCDETAILS输出详细的GC日志,虚拟机在退出之前打印堆栈信息。(以基准时间的形式),启动时间偏移后的JVM。//www.shouxicto.com/article/gc.log日志文件文件filethe输出path-xx:survivorratio = 8定义了伊甸园区域的空间比率和年轻一代中的幸存者区域是8:1-xmx设置程序运行启动时,最大的内存尺寸XMS设置程序会占用内存大小。Great启动是更快的-XMN设置的年轻一代占据内存size-xx:maxteningThreshold = n对象年龄到达n,下一个GC将进入老年,并且将分配Java对象的GC内存的内容。EGY章节介绍给所有人。
在大多数情况下,物体分配在伊甸园的新一代。
2.1.1.1 IDEA配置VM参数单击Drop -Down Arrow,单击编辑配置
单击+,单击应用程序
单击以选择相应的类,如果您想自己更改,名称将更改
配置VM参数,
-XMX64M -XMS64M -XMN10M -XX:+PRINTGCTIMESTAMPS -XX:+PRINTHEAPATGC -XX:+PRINTGCDETAILS
单击申请完成。
运行,查看输出:
解释:
Psyoungge的前PS代表垃圾收集器是平行的清除收藏家,而回收区域是新一代(Younggen);
总计9216K,总计7516K中的总数表示新一代可以使用总内存,而用户D表示使用内存。
以下是新一代的三个分区:从空间到空间的伊甸园空间,其大小的大小为8:1:1。
Paroldgen中的第一个标准杆代表垃圾收集器是平行的旧收藏家。回收区域是OldGen(OldGen),其中包含对象空间(对象区域),占100%。
Metaspace是JDK1.8的元空间,其中包含类空间。
伊甸园空间使用91%的使用,而从空间到空间,对象空间都使用0%,表明案例中的对象分配在伊甸园区域中。
虚拟机为每个对象定义一个对象年龄计数器。如果物体是在伊甸园之后出生的,并且在第一个小型GC之后,它仍然可以幸存,并且可以容纳幸存者。该物体在幸存者地区的未成年人GC幸存下来,年龄增加了一年。当它的年龄在一定程度上增加(默认的15岁)时,下一个GC将被提升为老年。对象被提升为最古老的年龄,并且可以通过参数-XX:MaxteningThreshord = n。
首先输入VM参数:
这意味着在第二个GC中,1年的物体将直接进入老年。
输出如下:
以上日志是在GC之前和之后打印桩内存信息。
GC信息说明:
查看其他信息:
GC调用后堆= 1(完整0)
在第一个GC之后表达信息,我们可以看到从1536K的空间中看到的57%,表明在第一个GC之后,幸存者区域占据了幸存者区域的一半
GC调用后堆= 2(完整0)
为了指示第二个GC之后的信息,我们可以看到Paroldgen总数为10240k,使用了732K,即幸存的物体已转移到老年。
更改-XX的值:MaxteningThreshold = 1至2,输出如下
我们可以看到,在第二GC之后的对象空间10240k,0%的用户,表明1年的对象尚未转移到老年。
为了更好地适应不同程序的内存状态,虚拟机并不总是要求对象的年龄到达MaxteningThreshold以促进老年。如果幸存者空间中相同年龄的总规模大于幸存者空间的一半,则年龄大于幸存者空间的年龄,并且年龄大于幸存者空间的年龄。可以直接进入老年,而无需等待MaxteningThreshold所需的年龄。
SO称为的大对象是指比剩余内存更大所需内存的对象。2.所需的连续内存空间大于其余连续内存空间的对象。
由于伊甸园和幸存者都无法容纳大物体,因此将尝试将它们直接晋升为老年。
虚拟机提供了-xx:PretenuresizEthrshold参数,该参数使对象大于将其直接分配在老年中的设置值。此参数仅适用于串行回收器和parnew,并且对平行GRALLALLGC回收器无效。默认值为0。
设置VM参数:
-XMX7M -XMS7M -XMN2M -XX:+PRINTGCDETAILS
对象没有年龄,因此默认值为15. run 3次,没有打开两个评论,打开第一个注释并打开第二个注释。结果如下:
第一的
第二次
第三次
从结果可以看出,由于2MB和3MB的对象大于新一代空间,因此它直接分配给了旧一代,从而导致记忆占据年龄。实际上,如果未分配将执行年龄,全GC,OOM例外。
对象主要分配在新一代的伊甸区,但是如果启动了本地线程分布缓冲区,则将其优先级,由tlab中的线程(线程局部Alocation Buffer。这是私有内存)。已初始化,它将适用于当前线程的指定内存。每个线程都有一个单独的缓冲区。如果要分配内存,您将在您自己的缓冲区上分配,但是当缓冲区容量不足时,请- 从伊甸园(Eden)区域申请继续使用它)。tlab的空间与伊甸园分开。
JDK1.8默认TLAB分配,您可以使用CMD命令Java -XX:+PrintFlagSfinal查看。
在次要GC发生之前,虚拟机会可以首先检查老年最大的连续空间是否大于新一代所有物体的总空间。如果建立了这种情况,则未成年人GC可以确保其安全。如果建立它,则可以检查句柄promotionfailure设置是否允许的虚拟机会。如果允许,它将继续检查最大的老年的连续空间大于促进到老年物体的平均大小。如果大于它,它将尝试执行次要的GC,尽管这次次要GC风险很高;或者处理promotionfailure设置不允许冒险,但此时必须将其更改为完整的GC。
如前所述,使用了新一代的复制收集算法,但是对于内存利用率,只有一个幸存者空间用作旋转备份。因此,当大量物体在未成年人GC之后仍能生存时,需要在老年人上执行。任务保证使该物体无法直接容纳幸存者到老年。但前提是有足够的空间可以在老年内容纳这些物体。但是,在完成内存恢复之前,不可能知道有多少物体幸存下来,因此我不得不将每个恢复的每次恢复到老年的平均值作为体验价值。与老年人的剩余空间相比,该年龄段的空间更多。
比较平均值仍然是一种动态概率方法,也就是说,如果未成年人GC的对象得以增加,它仍然会导致保证的保证失败。如果保证失败,则必须在后面启动完整的GC失败。
在JDK 6更新24之后,只要旧一代的连续空间大于新一代对象的总尺寸或上一个促销的平均大小,否则将执行完整的GC。参数将不再影响虚拟机的空间分配保证策略。
System.gc()还将同时触发老年人和新一代的回收。默认情况下,System.gc()将实时生效。它将以传统的完整GC方法(即串行+串行旧)恢复整个堆,并在参数中忽略USERG1GC和USECONCMARKSWEEPGC。
使用-xx:+explicitgcinvokesconcurrent,system.gc()是一种使用并发方法回收的显示GC。
通常,我们认为它会在垃圾回收过程中自动执行,并且不需要手动触发。频率垃圾回收对系统的性能有更大的影响。显示GC是禁用的,因此System.gc()等效于空函数。
对于默认并发回收的JVM,例如jdk1.8使用system.gc()在完整GC的面前触发yong gc。目的是首先收集新一代,以避免在相同的同一中避免所有回收工作是时候同时到达完整的GC,可以缩短一次。
案例,vm参数为-xx:+printgc
输出结果可以通过JDK1.8调用两个GC的GC方法。
作者:Liu Java