Java的垃圾收集

时间:2020-02-23 14:34:48  来源:igfitidea点击:

在本教程中,我们将看到Java中的垃圾收集。

我会尝试在图和示例的帮助下解释,而不是理论。

JVM存储器分为三个部分

  • 年轻代 Young generation
  • 老年代 Old generation
  • Metaspace (Perm Gen)

年轻代

顾名思义,年轻一代是新创建的对象被分配的区域。

  • 当年轻一代填满时,它会导致少量垃圾收集AKA次要GC。
  • 当次要GCS发生时,将从年轻一代中删除死亡对象。
  • 如果我们在年轻一代中有很多死亡对象,则未成年的GC将是更快的。
  • 所有次要GCS都是"停止世界"事件,因此当发生次要GCS时,应用程序线程也将停止。

让我们了解更多关于对象在年轻一代中分配的信息。

幼年分为3个部分。

  • 伊甸园空间
  • 幸存者空间S0
  • 幸存者空间S1

这是年轻人和旧代的插图。

  • 所有新创建的对象都在伊甸园空间中分配。
  • 当伊甸园空间完全填充对象时,将发生次要GC。所有未死亡或者未引用的对象将被移动到幸存者空间之一。在我们的情况下,让我们说所有对象都被移动到S0。
  • 当再次填充EDEN空间时,EDEN空间中的所有实时对象都将移动到SURVIVOR SPACE S1.
  • 一旦对象存活了多个小GC周期,它们将被移动到旧代。我们可以通过MaxTenuringThreshold控制此阈值。实际诱导阈值由JVM动态调整。

让我们尝试在榜样的帮助下演示此行为:我们有以下类,其中我正在为演示创建短暂的物体。

package org.igi.theitroad;
 
import java.math.BigDecimal;
 
public class GCCollectorExample {
	public static void main(String args[])
	{
		createObjects();
	}
	private static void createObjects() {
 
		long count = 0;
		
		while(true) { 
			//Creating short-lived objects just for illustration
			BigDecimal shortLivedBigDecimal1 = new BigDecimal(count++);
		}
	}
}

运行程序时。
让我们在Visual GC中查看内存分配(VisualVM插件)

如我们所见,我们在S0中有很少的对象,一旦eden空间完全填充,就会将所有引用的对象移动到S1.

老年代

  • 它用于持有旧的长幸存物体
  • 它通常大于年轻一代。
  • 当职业空间完全填充(或者预定义阈值)时,将发生主要GC。它会收回内存并释放空间。
  • 通常,主要的GCS比小GC更慢,频繁较少。

如何使用此信息来优化内存?
这取决于应用的性质。
如果我们有很多临时对象,那么将有很多次要GC。
我们可以提供参数xx:newratio = 1,将50%分发给年轻一代,50%到旧。
默认情况下,Newratio = 2因此年轻一代是总堆的1/3.
同样,如果我们有太多的长寿对象,那么我们可能需要通过换高价值的Newratio来增加任期空间的大小。

为什么两个幸存者空间?

你必须想知道为什么我们有2个幸存者空间。
我们有2个幸存者空间来避免内存碎片。
每次将对象从Eden复制到幸存者,我们都会获得空的Eden空间和1个空幸存者空间。

垃圾收集算法

JVM附带了几种年轻和旧代的算法。
有3种类型的算法

系列收集器

它使用单线线执行所有垃圾收集,适用于单个处理器机器的基本应用程序。

平行收集器

它使用多个CPU来执行垃圾收集器。
串行收集器使用1个线程执行GC,但并行GC使用多个线程执行GC,并且当有足够的内存和良好数量的核心时,它很有用。

并发收集器

并发收集器用应用程序线程执行垃圾收集。
它对于具有媒介到大型数据集的应用程序是有用的,并且需要快速响应时间。

我们可以为年轻人和旧代使用不同的GC算法,但我们只能对兼容兼容算法。

例如:我们不能将幼小一代的并行清除对旧的旧作物进行并行标记扫描,因为并行清除不提供CMS中所需的同步。

这是我们可以用于年轻和旧代的垃圾收集器。

Young CollectorOld CollectorJVM options
Serial (DefNew)Serial Mark-Sweep-Compact-XX:+UseSerialGC
Parallel scavenge (PSYoungGen)Serial Mark-Sweep-Compact (PSOldGen)-XX:+UseParallelGC
Parallel scavenge (PSYoungGen)Parallel Mark-Sweep-Compact (ParOldGen)-XX:+UseParallelOldGC
Serial (DefNew)Concurrent Mark Sweep-XX:+UseConcMarkSweepGC

-XX:-UseParNewGC
Parallel (ParNew)Concurrent Mark Sweep-XX:+UseConcMarkSweepGC

-XX:+UseParNewGC
G1-XX:+UseG1GC

垃圾收集器后Java 8有很多变化,我将尝试在我的下一个文章中覆盖它们。