JVM 调整GC



  • 调整GC

    在上一章中,我们了解了各种分代 Gcs。在本章中,我们将讨论如何调整GC。
  • 堆大小

    堆大小是影响Java应用程序性能的重要因素。如果它太小,那么它将经常被填充,结果,GC必须经常对其进行收集。另一方面,如果我们只是增加堆的大小,尽管需要减少收集频率,但是暂停应用程序线程的时间会增加。此外,增加堆大小会对基础OS造成严重损失。使用分页,操作系统使我们的应用程序看到的内存远远大于实际可用的内存。操作系统通过使用磁盘上的一些交换空间,将程序的非活动部分复制到磁盘中来管理此问题。当需要这些部分时,操作系统会将它们从磁盘复制回内存。让我们假设一台机器有8G的内存,而JVM看到了16G的虚拟内存,那么JVM不会知道实际上系统上只有8G可用。它只会从操作系统请求16G,一旦获得该内存,它将继续使用它。操作系统将必须交换大量数据进出,这将对系统造成巨大的性能损失。然后是在这种虚拟内存的完整GC期间会出现的停顿。由于GC将作用于整个堆进行收集和压缩,因此它将不得不等待大量时间才能将虚拟内存从磁盘中换出。在使用并发收集器的情况下,后台线程将不得不等待大量时间,以便将数据从交换空间复制到内存。因此,这里出现了如何确定最佳堆大小的问题。第一条规则是永远不要请求操作系统更多的内存。这将完全避免频繁交换的问题。如果机器已安装并正在运行多个JVM,则所有这些JVM的总内存请求将少于系统中的实际内存。
    您可以使用两个标志来控制JVM的内存请求大小-
    • -XmsN - 控制请求的初始内存。
    • -XmxN - 控制可以请求的最大内存。
    这两个标志的默认值取决于基础操作系统。例如,对于在MacOS上运行的64b JVM,-XmsN = 64M且-XmxN =最小1G或总物理内存的1/4。
    请注意,JVM可以在两个值之间自动调整。例如,如果发现发生了太多的GC,则只要它在-XmxN以下并且满足所需的性能目标,它就会继续增加内存大小。
    如果您确切知道应用程序需要多少内存,则可以设置-XmsN = -XmxN。在这种情况下,JVM不需要找出堆的“最佳”值,因此,GC流程变得更有效率。
  • 代大小

    您可以决定要分配给YG多少堆,以及要分配给OG多少堆。这两个值都通过以下方式影响我们的应用程序的性能。
    如果YG的大小很大,则收集频率会降低。这将导致较少数量的对象被提升为OG。另一方面,如果太大增加OG的大小,则收集和压缩它会花费太多时间,这将导致较长的应用程序暂停。因此,用户必须在这两个值之间找到平衡。
    以下是可用于设置这些值的标志-
    • -XX:NewRatio = N:YG与OG的比率(默认值= 2)
    • -XX:NewSize = N:YG的初始大小
    • -XX:MaxNewSize = N:YG的最大大小
    • -XmnN:使用此标志将NewSize和MaxNewSize设置为相同的值
    YG的初始大小由NewRatio的值通过给定公式确定-
    (总堆大小)/ (newRatio + 1 )
    由于newRatio的初始值为2,因此上述公式将YG的初始值为总堆大小的1/3。您始终可以通过使用NewSize标志明确指定YG的大小来覆盖此值。该标志没有任何默认值,如果未显式设置,则将使用上述公式继续计算YG的大小。
  • 永久空间和元空间

    永久和元空间是JVM保留类的元数据的堆区域。该空间在Java 7中被称为“永久空间”,在Java 8中被称为“元空间”。该信息由编译器和运行时使用。
    您可以使用以下标志控制该空间的大小:-XX:PermSize = N-XX:MaxPermSize参数 = N。可以使用-XX:Metaspace-Size = N和-XX:MaxMetaspaceSize = N来控制元空间的大小。
    未设置标志值时,如何管理永久位和元空间存在一些差异。默认情况下,两者都具有默认的初始大小。但是,尽管元空间可以根据需要占用尽可能多的堆,但是永久性最多只能占用默认的初始值。例如,64b JVM具有82M的堆空间作为最大永久大小。请注意,由于除非另有说明,否则元空间可以占用无限量的内存,因此可能会出现内存不足错误。每当调整这些区域的大小时,就会发生完整的GC。因此,在启动过程中,如果要加载很多类,则元空间可以不断调整大小,从而每次生成完整的GC。因此,如果初始元空间大小太小,大型应用程序将花费大量时间来启动。增大初始大小是一个好主意,因为这样可以减少启动时间。
    尽管永久性元数据和元空间保存了类元数据,但它不是永久性的,并且该空间像对象一样被GC回收。通常在服务器应用程序的情况下。每当您对服务器进行新的部署时,都必须清除旧的元数据,因为新的类加载器现在将需要空间。GC释放了该空间。