显式 GC 的使用:留与去,如何选择?
目录
一、什么是显式 GC?
(一) 垃圾回收的基本原理
(二)显式 GC 方法和行为
1. System.gc() 方法
2. 显式 GC 的行为
(三)显式 GC 的使用场景与风险
1. JVM 如何处理显式 GC
2. 显式 GC 的风险
二、显式 GC 对性能的影响
(一) 全 GC 与 STW
1. Full GC 是如何发生的?
2. STW(Stop-the-World)现象
3. Full GC 的性能开销
(二) 对 DirectByteBuffer 的影响
1. DirectByteBuffer 的垃圾回收问题
2. 显式 GC 的作用:避免内存泄漏
3. 禁用显式 GC 带来的问题
4. 解决方案:显式 GC 与优化参数
三、显式 GC 的争议
(一) 保留 System.gc():避免内存泄漏
1. DirectByteBuffer 和堆外内存的清理
2. 在长期运行的系统中避免资源泄漏
(二) 禁用 System.gc():减少性能损耗
1. 避免频繁的 Full GC 导致的 STW(Stop-the-World)停顿
2. 对 JVM 自适应回收策略的干扰
(三) 额外的 JVM 参数:优化显式 GC 的行为
1. -XX:+ExplicitGCInvokesConcurrent
2. -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
3. -XX:+UseConcMarkSweepGC 或 -XX:+UseG1GC
四、如何选择:留还是去?
(一) 保留显式 GC 的适用场景
1. 堆外内存管理需求
2. 需 要频繁类卸载的应用
3. 长时间运行的服务
(二)禁用显式 GC 的适用场景
1. 高并发、 低延迟要求
2. 现 代垃圾回收器的优化
3. 避免干扰自适应回收机制
(三) 如何优化显式 GC 以减少性能影响
1. 启用并发回收
2. 启用类卸载功能
3. 使用适合的垃圾回收器
五、小结
干货分享,感谢您的阅读!
在 Java 中,System.gc()
是一种显式触发垃圾回收的方式。然而,是否应该在代码中显式调用它,却是一个有争议的话题。有些开发者建议禁用显式 GC,因为它会导致不必要的性能开销,而另一些开发者则认为它在特定场景下是必要的。本文将分析显式 GC 的影响,并给出推荐的实践策略。
历史主要基本文章回顾:
涉猎内容 | 具体链接 |
Java GC 基础知识快速回顾 | Java GC 基础知识快速回顾-CSDN博客 |
垃圾回收基本知识内容 | Java回收垃圾的基本过程与常用算法_java垃圾回收过程-CSDN博客 |
CMS调优和案例分析 | CMS垃圾回收器介绍与优化分析案列整理总结_cms 对老年代的回收做了哪些优化设计-CSDN博客 |
G1调优分析 | Java Hotspot G1 GC的理解总结_java g1-CSDN博客 |
ZGC基础和调优案例分析 | 垃圾回收器ZGC应用分析总结-CSDN博客 |
从ES的JVM配置起步思考JVM常见参数优化 | 从ES的JVM配置起步思考JVM常见参数优化_es jvm配置-CSDN博客 |
深入剖析GC问题:如何有效判断与排查 | 深入剖析GC问题:如何有效判断与排查_排查java堆中大对象触发gc-CSDN博客 |
动态扩缩容引发的JVM堆内存震荡调优指南 | 动态扩缩容引发的JVM堆内存震荡:从原理到实践的GC调优指南 |
高频面试题汇总 | JVM高频基本面试问题整理_jvm面试题-CSDN博客 |
一、什么是显式 GC?
显式 GC(Explicit Garbage Collection),顾名思义,是指由程序员主动触发的垃圾回收过程。在 Java 中,显式 GC 是通过调用 System.gc()
方法来触发的。与 隐式 GC(由 JVM 自动管理的垃圾回收)不同,显式 GC 允许开发者手动干预垃圾回收的时机。
(一) 垃圾回收的基本原理
在 Java 中,垃圾回收器负责自动管理内存,回收不再被使用的对象。Java 堆内存通常分为以下几部分:
- Young Generation(年轻代):存放新创建的对象。随着对象的生命周期变长,一部分会被晋升到 Old Generation(老年代)。
- Old Generation(老年代):存放存活时间较长的对象。垃圾回收主要是在这里发生。
- MetaSpace:存储类元数据等。
JVM 的垃圾回收机制一般采用两种主要策略:
- Minor GC(年轻代回收):通常在 Young Generation 区域进行。
- Full GC(全堆回收):对整个堆(包括 Young 和 Old 区)进行回收。
通常,垃圾回收会由 JVM 自动触发,基于内存使用情况和垃圾回收的算法策略来决定。但有时开发者可能希望在特定时机手动触发垃圾回收,尤其是当确定内存压力较大或某些特定对象已经不再使用时。
(二)显式 GC 方法和行为
1. System.gc()
方法
System.gc()
方法是 Java 提供的一种显式触发垃圾回收的手段。调用 System.gc()
后,JVM 会尝试进行垃圾回收,尽管它并不一定立刻执行。具体执行什么类型的垃圾回收(如 Minor GC 或 Full GC)取决于 JVM 的实现和内存状态。
System.gc();
2. 显式 GC 的行为
调用 System.gc()
后,JVM 会进入垃圾回收的流程,但实际的执行行为可能有一些不同。具体来说,JVM 会根据当前的内存状态和 GC 策略,决定是否进行一次 Minor GC(年轻代回收)或者 Full GC(整个堆的回收)。例如,在使用 CMS GC 或 G1 GC 时,调用 System.gc()
会触发一个 Full GC,即对整个堆的回收。
需要注意的是,显式调用 System.gc()
并不保证回收一定会发生,它只是建议 JVM 尝试进行垃圾回收。实际执行与否,取决于 JVM 当前的状态、堆内存的使用情况以及系统资源。
(三)显式 GC 的使用场景与风险
显式 GC 一般用于以下几种场景:
- 内存泄漏的防范:如果某些对象(如 DirectByteBuffer)未能及时释放其堆外内存资源,开发者可以通过显式调用
System.gc()
来强制回收这些对象。 - 内存碎片化:在长时间运行的应用程序中,内存可能出现碎片化现象,显式 GC 可以帮助回收内存,尤其是在 Full GC 执行时,有可能通过压缩堆内存来减少碎片。
- 性能调优:在某些特定场景下(如高负载、内存压力大的时候),显式 GC 可能有助于提前清理无用对象,释放内存资源,从而避免由于内存不足导致的其他问题。
不过,需要注意的是,频繁调用显式 GC 可能会导致不必要的性能损耗,特别是在 STW(Stop-the-World) 阶段,应用的线程会被暂停,影响应用的响应能力。
1. JVM 如何处理显式 GC
JVM 提供了若干参数来控制显式 GC 的行为。例如:
-XX:+DisableExplicitGC
:禁用显式 GC,任何显式调用System.gc()
将不起作用。这个参数可以防止开发者误用System.gc()
,导致频繁的垃圾回收。-XX:+ExplicitGCInvokesConcurrent
:修改System.gc()
的行为,使其不会触发 Full GC,而是执行并发垃圾回收,从而减少 STW 时间。-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
:不仅执行并发垃圾回收,还会尝试卸载类。
显式 GC 在 JVM 中的处理方式,通常是调用 Universe::heap()->collect()
,该方法会触发垃圾回收,并执行整个堆的扫描。
2. 显式 GC 的风险
虽然 System.gc()
看似可以在需要时解决内存问题,但频繁调用显式 GC 会导致以下风险:
- 性能下降:频繁的 GC 操作会导致应用线程暂停,尤其是 Full GC,这会显著影响应用的响应时间和吞吐量。
- 内存管理问题:显式 GC 可能会错过 JVM 自动管理的最佳时机,导致垃圾回收在不合适的时机发生,进而影响系统的稳定性和性能。
因此,显式 GC 应该谨慎使用,尤其是在高负载和高并发的应用中。
二、显式 GC 对性能的影响
显式调用 System.gc()
会导致 JVM 触发垃圾回收,而这种操作对系统的性能有着直接的影响,尤其是当它触发 Full GC 时。理解其影响对于性能调优非常重要。
(一) 全 GC 与 STW
1. Full GC 是如何发生的?
在 JVM 中,Full GC 是指对整个堆内存(包括 Young Generation 和 Old Generation)的回收。这通常发生在以下几种情况:
- 老年代(Old Generation)内存不足,需要回收。
- Major GC 触发时,整个堆内存都会被扫描。
- 显式调用
System.gc()
时,JVM 会进行 Full GC,强制进行整个堆的回收。
Full GC 会涉及到对整个堆的扫描、标记和清理。由于涉及到的内存区域广泛且清理过程复杂,Full GC 的执行代价较高,尤其是在 老年代 存在大量数据时。
2. STW(Stop-the-World)现象
STW(Stop-the-World) 是指在执行垃圾回收期间,所有的应用线程都会被暂停。无论是 Minor GC 还是 Full GC,都可能涉及 STW,但 Full GC 的影响尤其明显。
- Minor GC:只会回收年轻代,通常比较轻量,停顿时间较短。
- Full GC:不仅会回收年轻代,还会回收老年代,并进行压缩等操作。其回收的范围和操作都比较复杂,导致停顿时间较长。
由于 Full GC 涉及到全堆回收,JVM 需要将所有应用线程暂停,并进行内存清理和压缩。停顿时间的长短取决于堆内存的大小、JVM 配置以及垃圾回收的效率。在堆内存较大的情况下,Full GC 的停顿时间可能会非常显著,这对高并发、高响应要求的系统来说,可能带来严重的性能问题。
3. Full GC 的性能开销
- 性能下降:每次执行 Full GC,应用线程必须被完全暂停,垃圾回收的执行期间无法处理业务逻辑。因此,Full GC 可能会导致用户请求的长时间阻塞,从而影响应用的响应时间和吞吐量。尤其是在高并发或低延迟的系统中,频繁的 Full GC 会让系统的性能大幅下降。
- 内存碎片化:Full GC 还可能引发内存碎片问题,特别是在采用 CMS GC 或 G1 GC 的情况下。回收过程中的内存压缩操作可能导致堆内存碎片化,从而影响内存的分配效率,进而影响系统的整体性能。
因此,频繁的显式 GC 调用尤其是在系统负载较高时,应该尽量避免,以减少 STW 时间,提升系统的响应能力。
(二) 对 DirectByteBuffer 的影响
DirectByteBuffer
是一种特殊的内存管理机制,使用的是 堆外内存(Native Memory),也称为直接内存。它允许 Java 程序直接与操作系统的内存交互,从而提高性能,尤其是在进行高性能 I/O 操作时,如使用 Netty、NIO 等框架时。
1. DirectByteBuffer 的垃圾回收问题
与堆内存不同,DirectByteBuffer 是基于堆外内存的对象,因此它并不受 JVM 的垃圾回收器直接管理。换句话说,DirectByteBuffer 对象的内存管理并不像普通的 Java 对象那样自动回收,JVM 只会管理堆内存中的对象。
DirectByteBuffer
的回收通常依赖于 JVM 显式触发垃圾回收,因为 JVM 必须通过 Full GC 来释放已经不再使用的堆外内存。当 System.gc()
被调用时,JVM 会强制进行一次 Full GC,从而对所有对象(包括堆外内存)进行清理。
如果显式调用 System.gc()
频繁地发生,那么它将强制触发 Full GC,从而确保已经无用的 DirectByteBuffer
对象的堆外内存得到及时释放。
2. 显式 GC 的作用:避免内存泄漏
由于 DirectByteBuffer 是通过堆外内存进行管理的,JVM 不会像处理普通 Java 对象那样自动处理其内存回收。如果禁用了显式 GC(例如使用了 -XX:+DisableExplicitGC
参数),并且 DirectByteBuffer 对象在长时间未被回收时,它们可能会导致 Native Memory OOM(堆外内存溢出)。
DirectByteBuffer
对象会通过 sun.misc.Cleaner
自动进行清理,该清理器会在对象被 GC 后释放堆外内存。然而,只有在发生 Full GC 时,DirectByteBuffer
的清理工作才会进行,因此频繁的显式调用 System.gc()
会确保堆外内存及时得到清理。
3. 禁用显式 GC 带来的问题
如果禁用显式 GC(通过 -XX:+DisableExplicitGC
),JVM 将不再响应 System.gc()
调用。这可能导致以下问题:
-
DirectByteBuffer 的堆外内存泄漏:如果没有触发 Full GC,
DirectByteBuffer
的堆外内存就不会被释放,这可能导致堆外内存的不断增加,最终导致 Native Memory OOM(堆外内存溢出)。这种情况通常出现在高负载的 NIO 应用中,尤其是使用大量直接内存的场景下。 -
内存压力增大:对于依赖堆外内存的应用程序,禁用显式 GC 后,JVM 将不再定期清理这些内存,导致内存压力增大,从而影响系统的稳定性和性能。
4. 解决方案:显式 GC 与优化参数
为了解决显式 GC 带来的问题,特别是在处理 DirectByteBuffer 时,JVM 提供了几个优化参数:
-
-XX:+ExplicitGCInvokesConcurrent
:这个参数会让显式调用System.gc()
时,执行并发垃圾回收,而不是触发 Full GC。通过这种方式,可以减少 STW 的时间,并且执行垃圾回收时,DirectByteBuffer
的清理也会更及时。 -
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
:这个参数不仅会执行并发回收,还会在回收时卸载类,减少类的加载压力。它对于减少内存占用和提高系统的回收效率有很大帮助。
通过这些优化参数,能够保证 DirectByteBuffer
的清理不至于因为禁用显式 GC 而导致内存泄漏,同时降低 STW 的影响。
三、显式 GC 的争议
显式 GC 的使用一直存在较大的争议,主要是因为它在不同的应用场景中带来的影响各异。显式调用 System.gc()
可以帮助管理堆外内存等资源,但也会带来较大的性能损失,尤其是在高并发、低延迟的系统中。接下来,我们将从保留和禁用显式 GC 两个角度,分析它们各自的利与弊,并介绍一些可以帮助优化显式 GC 行为的 JVM 参数。
(一) 保留 System.gc():避免内存泄漏
显式调用 System.gc()
在某些特定场景下仍然是非常必要的,尤其是在 堆外内存(Direct Memory)的管理上,保留显式 GC 的常见场景:
1. DirectByteBuffer 和堆外内存的清理
DirectByteBuffer 是 Netty 等高性能网络框架广泛使用的一种堆外内存缓冲区。由于堆外内存不受 JVM 垃圾回收机制的直接管理,它需要通过 sun.misc.Cleaner 来进行清理,而这个过程只有在 Full GC 时才能被触发。频繁的显式调用 System.gc()
可以迫使 JVM 进行 Full GC,从而清理这些不再使用的 DirectByteBuffer 对象及其关联的堆外内存。
- 内存泄漏的风险:如果没有适时清理堆外内存,系统中可能会累积大量的无用 DirectByteBuffer 对象,导致内存泄漏,最终引发 Native Memory OOM(堆外内存溢出)。因此,保留显式 GC 可以在一定程度上避免这种情况,尤其是在涉及到大量 Netty 或 NIO 操作的高并发应用中。
2. 在长期运行的系统中避免资源泄漏
对于长期运行的应用程序,尤其是有大量 DirectByteBuffer 分配和回收的场景,定期触发 Full GC 可以确保堆外内存得到及时释放。在这种情况下,保留 System.gc()
可以作为防止长期资源泄漏的手段。否则,内存泄漏的后果可能会在系统运行一段时间后显现,导致性能严重下降或崩溃。
(二) 禁用 System.gc():减少性能损耗
尽管显式 GC 在某些场景下有其必要性,但它会显著影响应用的性能,尤其是当频繁调用 System.gc()
时。禁用显式 GC 的几个主要原因:
1. 避免频繁的 Full GC 导致的 STW(Stop-the-World)停顿
在 CMS GC 或 G1 GC 等垃圾回收器中,频繁调用 System.gc()
会触发 Full GC,从而导致应用线程停止(STW)。这种停顿对高并发、低延迟要求的应用尤为致命。特别是在大规模分布式系统或实时系统中,Full GC 的停顿时间可能会导致应用响应时间大幅增加,严重时甚至会导致系统崩溃。
- 性能损失:频繁的 STW 停顿会显著影响系统的响应性,尤其是对于低延迟要求极高的应用,如高频交易系统、实时数据分析平台等。
2. 对 JVM 自适应回收策略的干扰
JVM 中的垃圾回收器通常具备 自适应 功能,会根据系统的内存使用情况自动调整回收策略。如果频繁调用显式 GC,会干扰这些自适应机制,影响其优化效果。例如,CMS 和 G1 GC 会根据历史的回收效率来动态调整触发 GC 的时机和策略,频繁调用 System.gc()
会导致 JVM 对垃圾回收的自适应调节失效,从而影响性能。
- 干扰自适应机制:禁用显式 GC 可以确保 JVM 自主选择最佳的垃圾回收时机和策略,避免人为干扰。
(三) 额外的 JVM 参数:优化显式 GC 的行为
为了减少显式 GC 带来的性能损耗,JVM 提供了一些参数可以帮助优化显式 GC 的行为。使用这些参数时,系统可以在触发显式 GC 时,采用更加高效、并发的回收策略,从而减少停顿时间。
1. -XX:+ExplicitGCInvokesConcurrent
该参数会将显式 GC 的回收模式从传统的 Stop-the-World Full GC 改为 并发回收(Concurrent GC)。这样,当 System.gc()
被调用时,JVM 会尝试以并发方式进行垃圾回收,避免所有应用线程被暂停。
- 优势:并发回收模式能显著减少 STW 停顿时间,尤其适用于对响应时间敏感的应用。
- 适用场景:适合高并发、低延迟应用,尤其是在需要频繁调用显式 GC 来释放内存的场景下,能够提高系统的吞吐量和响应速度。
2. -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
这个参数在 -XX:+ExplicitGCInvokesConcurrent
的基础上,进一步增强了类的卸载功能。在 Full GC 的过程中,除了进行并发回收外,还会尝试卸载不再使用的类,释放类加载器的内存占用。
- 优势:对于一些大型应用,尤其是长时间运行且存在类加载和卸载的场景(如 Web 应用、应用服务器等),这个参数可以帮助回收不再使用的类,减少内存压力。
- 适用场景:适用于内存占用较大、类加载频繁的应用,尤其是对内存管理要求较高的场景。
3. -XX:+UseConcMarkSweepGC
或 -XX:+UseG1GC
如果决定保留显式 GC,但又希望减少 Full GC 带来的停顿,可以启用 CMS GC 或 G1 GC。这两个垃圾回收器都能提供并发和低停顿的回收方式,尤其是在大内存应用中能够更平滑地进行垃圾回收,避免全量 GC 导致的停顿。
- 优势:通过并发收集机制,能够减少 GC 时的停顿,并提高系统的吞吐量。
- 适用场景:适合内存较大、需要平衡吞吐量和响应时间的应用,如大数据处理系统、服务器应用等。
通过合理选择显式 GC 的使用方式和参数,可以在保证内存管理的同时,最大化地减少对性能的影响。
四、如何选择:留还是去?
在显式 GC 的使用中,我们需要根据应用的具体需求、性能目标以及内存管理策略来决定是否保留 System.gc()
。
(一) 保留显式 GC 的适用场景
虽然显式 GC 带来一定的性能损耗,但在某些场景下,它却是不可或缺的。
1. 堆外内存管理需求
对于 DirectByteBuffer 等直接内存的使用,JVM 并不会自动管理堆外内存的回收,这意味着这些内存必须由应用程序手动释放。在此类应用中,定期调用 System.gc()
可以强制进行 Full GC,从而清理堆外内存,避免内存泄漏。
- 典型场景:高性能框架(如 Netty)通常使用堆外内存来减少 GC 压力,这时定期的显式 GC 调用就显得尤为重要。否则,堆外内存的释放可能因没有足够的触发机制而延迟,导致内存泄漏,进而导致 Native Memory OOM(堆外内存溢出)。
2. 需 要频繁类卸载的应用
一些需要频繁加载和卸载类的应用,如长时间运行的 Java Web 应用,可能会遇到类加载器无法及时卸载类的问题。在这些情况下,显式 GC 可以帮助清理不再使用的类,确保内存得到及时回收。
3. 长时间运行的服务
对于一些长期运行的服务(例如 Web 服务器或后台任务处理系统),显式 GC 可以有效减少由于内存泄漏引起的堆积问题,尤其是在内存长时间未触发 GC 的情况下。
(二)禁用显式 GC 的适用场景
在许多场景中,频繁调用显式 GC 会带来不必要的性能损耗,尤其是在高并发、低延迟要求较高的系统中。
1. 高并发、 低延迟要求
在高并发、低延迟的系统中,显式调用 System.gc()
会引发 Stop-the-World (STW) 停顿,这可能导致响应延迟增加,影响吞吐量。例如,金融交易、实时数据流处理等应用场景对响应时间和吞吐量有严格要求,显式 GC 会中断业务线程,导致停顿时间不可预测。
2. 现 代垃圾回收器的优化
禁用显式 GC 后,JVM 会依赖其内建的垃圾回收机制,如 G1 GC 或 ZGC,这些回收器具有自适应的调度和优化策略,能够根据堆内存的使用情况自动调整回收方式,从而减少停顿和提高吞吐量。在大多数现代 JVM 中,这些自动优化机制的效果已经相当优秀,因此禁用显式 GC 可以让 JVM 更好地进行内存回收。
3. 避免干扰自适应回收机制
频繁调用显式 GC 会干扰 JVM 的自适应回收机制,导致垃圾回收时机的不合理选择,从而降低垃圾回收的效率。禁用显式 GC 可以避免这种干扰,让 JVM 根据实际内存压力来自动选择最合适的回收策略。
(三) 如何优化显式 GC 以减少性能影响
如果你决定保留显式 GC,但又不希望它带来过大的性能损失,可以通过以下几种方式来优化显式 GC 的影响:
1. 启用并发回收
使用 -XX:+ExplicitGCInvokesConcurrent
参数可以将显式 GC 从全量回收模式改为并发回收模式。这样,即使调用了 System.gc()
,JVM 也会尽量在后台并发进行垃圾回收,减少 Stop-the-World 停顿时间。
- 适用场景:适用于对性能有较高要求的应用,在需要保留显式 GC 的同时,降低 GC 带来的停顿时间,保持系统的响应性。
2. 启用类卸载功能
使用 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
参数,可以使显式 GC 不仅进行并发回收,还能尝试卸载类,释放类加载器的内存。这个优化对于一些需要频繁加载和卸载类的应用(如微服务架构、容器化应用等)尤其重要,能够有效防止类加载器内存泄漏。
3. 使用适合的垃圾回收器
现代 JVM 提供了多种垃圾回收器选择,适合不同类型的应用。例如,使用 G1 GC 或 ZGC 可以提供低延迟的回收策略。为了提高系统的内存回收效率,可以选择使用这些回收器,并将显式 GC 调用的时机交给 JVM 来决定。
- G1 GC:适合大规模堆内存和要求低延迟的系统,能够平衡吞吐量和停顿时间。
- ZGC:专为低延迟需求设计,几乎消除 Stop-the-World 停顿,非常适合对实时性有极高要求的应用。
显式 GC 的使用是否合适,关键在于应用的特点和需求。通过合理选择是否使用显式 GC,结合适当的 JVM 参数优化,能够在不牺牲性能的情况下,确保系统的内存得到高效管理。
五、小结
显式 GC 在特定场景下是不可或缺的,尤其是在需要手动管理堆外内存或确保资源及时回收时。然而,频繁调用 System.gc()
会触发 Full GC,进而导致 Stop-the-World (STW) 停顿,对系统性能产生显著影响。
因此,是否保留显式 GC 需要根据具体的应用需求来判断:
-
对于高性能、低延迟的系统,频繁的显式 GC 会带来过大的停顿时间,影响系统响应和吞吐量。在这类场景中,禁用显式 GC 更为合适,让 JVM 的自动垃圾回收机制发挥作用,提升系统的稳定性与响应能力。
-
对于需要精细控制堆外内存(如 DirectByteBuffer)或特定资源回收的应用,保留显式 GC 是必要的。通过显式触发 GC 可以确保这些资源及时回收,防止内存泄漏或堆外内存溢出。此时,可以通过调整 JVM 参数(如
-XX:+ExplicitGCInvokesConcurrent
或-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
)来减小显式 GC 对性能的影响,确保回收过程高效且不会过度干扰业务。
综上所述,合理配置和使用 System.gc()
,结合合适的 JVM 调优策略,才能在性能和内存管理之间找到最优的平衡点。在实际应用中,我们需要根据系统的业务需求、性能目标和资源管理需求做出灵活的选择,避免盲目启用或禁用显式 GC。
相关文章:

显式 GC 的使用:留与去,如何选择?
目录 一、什么是显式 GC? (一) 垃圾回收的基本原理 (二)显式 GC 方法和行为 1. System.gc() 方法 2. 显式 GC 的行为 (三)显式 GC 的使用场景与风险 1. JVM 如何处理显式 GC 2. 显式 GC…...

探秘基带算法:从原理到5G时代的通信变革【二】Viterbi解码
文章目录 二、关键算法原理剖析2.1 Viterbi 解码2.1.1 卷积码与网格图基础**卷积码****网格图****生成多项式****理想情况下解码过程** 2.1.2 Viterbi 算法核心思想2.1.3 路径度量与状态转移机制2.1.4 算法流程与关键步骤详解2.1.5 译码算法举例与复杂度分析2.1.6 算法代码示例…...

从零实现高并发内存池
目录 一、项目介绍 二、什么是内存池? 1.池化技术 2.内存池 3.内存池解决的问题 三、malloc本身就是内存池 四、定长内存池 五、高并发内存池整体框架 六、thread cache 七、central cache 八、page cache 一、项目介绍 当前项目是实现一个高并发的内存池…...
3-7 WPS JS宏 工作表移动复制实例-2(多工作簿的多工作表合并)学习笔记
************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…...

【计算机网络】考研复试高频知识点总结
文章目录 一、基础概念1、计算机⽹络的定义2、计算机⽹络的目标3、计算机⽹络的组成4、计算机⽹络的分类5、计算机⽹络的拓扑结构6、计算机⽹络的协议7、计算机⽹络的分层结构8、OSI 参考模型9、TCP/IP 参考模型10、五层协议体系结构 二、物理层1、物理层的功能2、传输媒体3、 …...

IDEA Tab 页设置多行显示
前言 日常编码中,经常需要在编辑器中同时打开多个文件,而在 IDEA 中,默认情况下,顶部的 Tab 页只显示一行,多余的文件会被隐藏起来,如下图所示: IDEA 默认 Tab 页只显示一行 这种情况下&#…...
Spark核心之02:常用算子详解
1、RDD操作详解 # 启动spark-shell spark-shell --master local[2] 1.1 基本转换 1) map map是对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD。 任何原RDD中的元素在新RDD中都有且只有一个元素与之对应。 举例: scala> val a sc.parallelize(1 …...

Redis---LRU原理与算法实现
文章目录 LRU概念理解LRU原理基于HashMap和双向链表实现LRURedis中的LRU的实现LRU时钟淘汰策略近似LRU的实现LRU算法的优化 Redis LRU的核心代码逻辑Redis LRU的核心代码逻辑Redis LRU的配置参数Redis LRU的优缺点Redis LRU的优缺点 LRU概念理解 LRU(Least Recentl…...

matlab 包围盒中心匹配法实现点云粗配准
目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、初始位置2、配准结果本文由CSDN点云侠原创,原文链接,首发于:20255年3月3日。 一、算法原理 1、原理概述 包围盒中心匹配法是将源点云 P P P...

Mermaid语法介绍
一、基础语法 图表声明 使用 graph TD(自上而下)或 graph LR(从左到右)定义图表方向,节点间用箭头连接。例如: #mermaid-svg-WLayaaK0Ui6cKr5Z {font-family:"trebuchet ms",verdana,arial,sans…...
RHCE9.0版本笔记3:创建、查看和编辑文本文件
一、文件操作在RHCE中的核心地位 无论是配置系统服务(如httpd/sshd)、编写Ansible Playbook,还是分析日志文件,都离不开对文本文件的精确控制。 文件创建四大技法 1.快速创建空文件 # 标准创建方式 $ touch server.conf # 批量…...

VSCode知名主题带毒 安装量900万次
目前微软已经从 Visual Studio Marketplace 中删除非常流行的主题扩展 Material Theme Free 和 Material Theme Icons,微软称这些主题扩展包含恶意代码。 统计显示这些扩展程序的安装总次数近 900 万次,在微软实施删除后现在已安装这些扩展的开发者也会…...
deepseek、腾讯元宝deepseek R1、百度deepseekR1关系
分析与结论 区别与联系 技术基础与定制方向: DeepSeek官网R1版本:作为基础版本,通常保留通用性设计,适用于广泛的AI应用场景(如自然语言处理、数据分析等)。其优势在于技术原生性和官方直接支持。腾讯元宝…...

二、QT和驱动模块实现智能家居-----5、通过QT控制LED
在QT界面,我们要实现点击“LED”按钮就可以控制板子上的LED。LED接线图如下: 在Linux 系统里,我们可以使用2种方法去操作上面的LED: ① 使用GPIO SYSFS系统:这需要一定的硬件知识,需要设置引脚的方向、数值…...

基于Android平台的SOME/IP测试模块 EPT-ETS
在汽车产业智能化、网联化的时代浪潮中,汽车电子系统正经历着前所未有的变革。SOME/IP(Scalable service-Oriented MiddlewarE over IP)协议作为汽车电子通信领域的关键技术,其稳定性、可靠性与高效性对于整车性能的提升起着至关重…...

QT实现计算器
1:在注册登录的练习里面, 追加一个QListWidget 项目列表 要求:点击注册之后,将账号显示到 listWidget上面去 以及,在listWidget中双击某个账号的时候,将该账号删除 Widget.h #ifndef WIDGET_H #define…...

Go红队开发—语法补充
文章目录 错误控制使用自定义错误类型错误包装errors.Is 和 errors.Aspanic捕获、recover 、defer错误控制练习 接口结构体实现接口基本类型实现接口切片实现接口 接口练习Embed嵌入文件 之前有师傅问这个系列好像跟红队没啥关系,前几期确实没啥关系,因为…...
二、Redis 安装与基本配置:全平台安装指南 服务器配置详解
Redis 安装与基本配置:全平台安装指南 & 服务器配置详解 Redis 作为高性能的内存数据库,其安装和配置是使用 Redis 的第一步。本篇文章将全面介绍 Redis 的安装方式,覆盖 Windows、Linux、Docker 环境,并详细讲解 Redis 的基础配置,包括 持久化、日志、端口设置等。此…...

halcon学习笔记1
环境的搭建就不说了,主要是作者在入职后的实际学习与实践。 打开应用程序 这里作者的个人理解是1号区域主要是可以观察到读取的图像以及后续对图像进行何种操作,2的算子类似于Opencv中的API,可以在上面进行参数的调整,例如read_I…...
解决Docker拉取镜像超时错误,docker: Error response from daemon:
当使用docker pull或docker run时遇到net/http: request canceled while waiting for connection的报错,说明Docker客户端在访问Docker Hub时出现网络连接问题。可以不用挂加速器也能解决,linux不好用clash。以下是经过验证的方法(感谢轩辕镜…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...