当前位置:首页 > 数码 > 掌握JVM性能调优-GC机制-释放Java应用潜能!-深入Java (jvm的理解)

掌握JVM性能调优-GC机制-释放Java应用潜能!-深入Java (jvm的理解)

admin3个月前 (04-26)数码15

JVM 性能调优是一个复杂的过程,需要结合具体的应用程序特性和需求来进行调优。不同的应用场景可能需要不同的调优策略。对于开发人员来说,进行程序的性能优化是很有挑战的工作,也是很有意义的一件事。

JVM 内存模型

JVM 架构应该已经使用了一些像这样的 JVM 配置:

JAVA_OPTS=-server -Xms2560m -Xmx2560m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:MetaspaceSize=768m -XX:MaxMetaspaceSize=768m -XX:InitialCodeCacheSize=64m -XX:ReservedCodeCacheSize=96m -XX:MaxTenuringThreshold=5″

那么 JVM 是如何驻留在内存上的?

JVM 消耗主机操作系统内存上的可用空间。在 JVM 内部,存在独立的内存空间(堆、非堆、缓存),以存储运行时数据和编译后的代码。

堆内存

以下是有关服务器应用程序堆大小的一般准则:

  • 年轻代(Young Generation)
  • 老年代(Old Generation)

非堆内存

  • 高速缓存存储器

什么是 GC?

Java 通过一个称为废品收集器的程序提供自动内存管理。移除不再使用的对象。

上面的一切都是在堆中完成的,堆是运行时动态内存分配的空间,用于包含所有 java 对象。除了堆之外,还有堆栈,其中包含支持线程执行的局部变量和函数调用。

Java 废品收集的实际工作原理

许多人认为废品收集会收集并丢弃死对象。事实上,Java 废品收集的作用恰恰相反!活动对象被跟踪,其他所有对象都被指定为废品。

这种根本性的误解可能会导致许多性能问题。让我们从堆开始,它是用于动态分配的内存区域。在大多数配置中,操作系统会提前分配堆,以便在程序运行时由 JVM 管理。这有几个重要的影响:

  • 新对象简单地分配在已用堆的末尾
  • 一旦某个对象不再被引用并且因此应用程序代码无法访问该对象,废品收集器就会将其删除并回收未使用的内存

每个对象树必须有一个或多个根对象。只要应用程序可以到达这些根,那么整棵树都是可以到达的。但是这些根对象什么时候被认为是可达的呢?

称为废品收集根,它是特殊对象始终是可访问的,任何在其根处具有废品收集根的对象也是如此。Java中有四种GCroot:

  • GC 根是 JVM 本身引用的对象,因此可以防止其他所有对象被废品收集

因此,一个简单的 Java 应用程序具有以下 GC 根:

  1. 程序计数器
  2. 虚拟机栈
  3. 本地方法栈
  4. 方法区

标记并清除废品

为了确定哪些对象不再使用,JVM 间歇性地运行所谓的标记和清除算法。正如所直觉的,这是一个简单的两步过程:

  1. 标记活动对象
  2. 删除未使用的对象

活动对象在上图中表示为蓝色。当标记阶段结束时,每个活动对象都被标记。因此,所有其他对象(上图中的灰色数据结构)都无法从 GC根访问,这意味着应用程序无法再使用无法访问的对象。此类对象被视为废品,GC 应在以下阶段中删除它们。

标记阶段需要注意以下重要方面:

  • 标记过程在应用程序运行时进行,这意味着 GC 可能会暂停应用程序线程。
  • 标记过程可能需要大量时间,具体取决于应用程序正在使用的对象数量。

删除未使用的对象

对于不同的 GC 算法,未使用对象的删除略有不同,但所有此类 GC 算法都可以分为三步:清除(sweeping)、压缩(compacting)和复制(copying)。

标记和清除算法在概念上使用最简单的废品处理方法,即忽略此类对象。这意味着在标记阶段完成后,未访问对象占用的所有空间都被视为空闲,因此可以重用以分配新对象。该方法需要使用所谓的空闲列表记录每个空闲区域及其大小。空闲列表的管理增加了对象分配的开销。

这种方法还有另一个弱点——可能存在大量空闲区域,但如果没有一个区域足够大来容纳分配,分配仍然会失败(在 Java 中会出现 OutOfMemoryError 错误)。它通常被称为标记-清除算法。

Mark-Sweep-Compact 算法通过将所有标记的对象(即活动的对象)移动到堆的另一部分,从而删除未使用的对象。这将所有活动对象集中在一起,从而减少了应用程序的内存碎片。但是,此算法可能会导致 GC 暂停应用程序线程,具体取决于要移动的对象数量。

复制算法将活动对象复制到新分配的内存区域,并释放原始区域中所有未使用的对象。与 Mark-Sweep-Compact 算法相比,此算法不会产生内存碎片,但它需要更多的内存开销,具体取决于要复制的对象数量。

性能调优

JVM 性能调优是一个复杂的过程,涉及到许多因素。以下是一些提示,可以帮助您优化应用程序的性能:

  • 使用合适的 GC 算法。对于堆大小较小且对象生命周期较短的应用程序,标记-清除算法可能是最佳选择。对于堆大小较大且对象生命周期较长的应用程序,复制算法可能是更好的选择。
  • 调整堆大小。堆大小是影响 GC 性能的重要因素。堆大小应该足够大,以避免频繁的 GC 暂停,但它也不应该太大,以至于导致应用程序内存不足。
  • 使用内存分析工具。有许多可用于分析应用程序内存使用的工具。这些工具可以帮助您识别内存泄漏和其他性能问题。
  • 监控 GC 性能。使用 Java Management Extensions(JMX)等工具监控 GC 性能可以帮助您识别潜在问题。

结论

JVM 性能调优是一个复杂的过程,需要结合具体的应用程序特性和需求来进行调优。不同的应用场景可能需要不同的调优策略。通过理解 JVM 内存模型和废品回收的实际工作原理,您可以提高应用程序的性能并降低内存消耗。


JVM 调优工具有哪些?

Java虚拟机(JVM)调优是提高Java应用程序性能的重要步骤之一。 以下是一些常用的Java JVM调优工具: - VisualVM:这是Oracle官方提供的免费工具,可以监视和分析Java应用程序的性能。 - JConsole:这是Oracle官方提供的免费工具,可以监视和分析Java应用程序的性能。 - JDK自带的JIT编译器:可以通过调整JIT编译器的参数来提高Java应用程序的性能。 - JProfiler:这是一个商业工具,可以提供更详细的分析和报告,以及更多的性能优化选项。

JVM性能调优(2) —— 内存设置和查看GC日志

1)JVM内存分配有如下一些参数:

一般 -Xms 和 -Xmx 设置一样的大小,-XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 设置一样的大小。-Xms 等价于 -XX:InitialHeapSize,-Xmx等价于-XX:MaxHeapSize;-Xmn等价于-XX:MaxNewSize。

2)在IDEA中可以按照如下方式设置JVM参数:

3)命令行启动时可以按照如下格式设置:

1)设置GC参数:

可以在启动时加上如下参数来查看GC日志:

例如,我在IDEA中添加了如下JVM启动参数:

jvm的理解

启动程序之后打印出了如下的一些日志:

从第三行 CommandLine flags 可以得到如下的信息:

2)查看默认参数:

如果要查看JVM的默认参数,就可以通过给JVM加打印GC日志的参数,就可以在GC日志中看到JVM的默认参数了。

还可以在启动参数中添加 -XX:+PrintFlagsFinal 参数,将会打印系统的所有参数,就可以看到自己配置的参数或系统的默认参数了:

3)GC日志:

之后的日志就是每次废品回收时产生的日志,每行日志说明了这次GC的执行情况,例如第四行GC日志:

详细内容如下:

2020-09-25T13:00:41.631+0800:GC发生的时间点。 4.013:系统运行多久之后发生的GC,单位秒,这里就是系统运行 4.013 秒后发生了一次GC。 GC (Allocation Failure):说明了触发GC的原因,这里是指对象分配失败导致的GC。 PSYoungGen:指触发的是年轻代的废品回收,使用的是 Parallel Scavenge 废品回收器。 K->K:对年轻代执行了一次GC,GC之前年轻代使用了 K,GC之后有 K 的对象活下来了。 (K):年轻代可用空间是 K,即 461 M,为什么是461M呢?因为新生代大小为 512M,Eden 区占 409.6M,两块 Survivor 区各占 51.2M,所以年轻代的可用空间为 Eden+1个Survivor的大小,即460.8M,约为461M。 K->K:GC前整个堆内存使用了 K,GC之后堆内存使用了 K。 (K):整个堆的大小是 K,即 973M,其实就是年轻代的 461M + 老年代的 512 M 0. secs:本次GC耗费的时间 Times: user=0.00 sys=0.00, real=0.01 secs:本次GC耗费的时间 4)JVM退出时的GC情况:

程序结束运行后,还会打印一些日志,就是第12行之后的日志,这部分展示的是当前堆内存的使用情况:

详细内容如下:

免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。

标签: Java

“掌握JVM性能调优-GC机制-释放Java应用潜能!-深入Java (jvm的理解)” 的相关文章

深入探讨-Java-编程中的类继承与接口实现 (深入探讨交流)

深入探讨-Java-编程中的类继承与接口实现 (深入探讨交流)

简介 类索引、父类索引和接口索引是在 Class 文件中用于确定类的继承关系的重要数据。通过这些索引,Java 虚拟机 (JVM) 可以准确地建立类之间的继承关系,实现多态性和接口的实现。...

大编程趋势-5-年-Java-2024-开发者的 (编程是大趋势吗)

大编程趋势-5-年-Java-2024-开发者的 (编程是大趋势吗)

Java 作为编程领域的支柱,拥有超过 900 万开发人员和超过 30 年的发展历史。它以其先进的安全功能、优越的性能和跨平台开发能力而闻名。展望 2024 年,Java 正准备进行一场突破性的转...

选择性-过多的关键词会增加SEO工作的复杂性-关键词不应过多 (选择性太多)

选择性-过多的关键词会增加SEO工作的复杂性-关键词不应过多 (选择性太多)

引言 在不断演进的软件开发领域,保持最新技术至关重要。从 Java 11 迁移到 Java 21 是一个明智的决定,它带来了显着的优势和创新,可以提升应用程序的安全性、性能和开发效率。...

Java循环结构与实现方式 (java循环语句案例)

Java循环结构与实现方式 (java循环语句案例)

循环简介 循环是编程中常用的一种控制结构,用于重复执行某一段代码或操作。循环的执行需要满足一定的条件,当条件满足时,循环会一直执行,直到条件不满足时才结束。所以循环其实就是重复地完成某一件事...

Java-Lambda-表白式的多面运行-从基础到初级 (java类的定义和使用)

Java-Lambda-表白式的多面运行-从基础到初级 (java类的定义和使用)

Lambda表白式是8中引入的最有影响力的性能之一。它们经过准许繁复而优雅地创立匿名函数来成功Java中的函数式编程。在这篇博文中,咱们将讨论编写lambda表白式的各种方式。 概述...

在-Java-年依然盛行的-2023-25-个要素 (在javascript中)

在-Java-年依然盛行的-2023-25-个要素 (在javascript中)

译者|刘汪洋 审校|重楼 学习的环节中,我看法到在90年代末OOP正值鼎盛期间,Java作为能够真正成功这些概念的言语显得尤为突出(虽然我此前学过C++,但相比Java影响较小)。我特...

Java中不倡导经常使用foreach的六大场景 (java中不等于怎么写)

Java中不倡导经常使用foreach的六大场景 (java中不等于怎么写)

在中,foreach是一个罕用的循环结构,它可以极大地简化遍历数组或汇合(例如List或Set)的代码。它通常被以为是一种愈加繁复和易读的迭代形式。但是,或许有一些状况下不倡导经常使用foreac...

Java-渣滓回收器的运作形式-对不再沉闷对象的跟踪机制

Java-渣滓回收器的运作形式-对不再沉闷对象的跟踪机制

作为一门面向对象的编程言语,具备智能内存治理的个性。这象征着开发人员无需手动调配和监禁内存,而是由Java虚构机的渣滓回收器担任治理。渣滓回收器经过监督程序中不再经常使用的对象来回收内存,以提高内...