JVM——一个神圣的话题,可远观而不可亵玩焉

一切不仅仅为了面试

提示:仅仅代表个人理解

JVM调优理解

JVM调优是指调整和配置JVM的参数以优化运行Java应用程序的性能,主要目标是提高应用的响应速度和提高应用的吞吐量减少延迟以及确保资源高效使用。调优通常针对内存管理垃圾收集策略线程堆栈大小等方面进行。

JVM调什么:

提示:这里我就想吐槽一下:不要没病乱吃药,同样JVM没啥问题不要乱调

分析应用的性能特征:首先需要使用诊断工具(如jConsole、VisualVM、JProfiler等)收集Java应用的运行时数据。

确定调优目标:了解应用的需求,是否关注高吞吐量、低延迟还是内存使用效率等。

选择合适的垃圾收集器:基于应用需求选择合适的垃圾收集器,如CMS、G1、ZGC等。

调整内存分配:分析并设置适当的堆内存大小、新生代和老年代的比例、元空间大小等。

调整性能参数:例如调整JIT编译器行为、线程堆栈的大小等。
(JIT是"Just-In-Time"编译器的缩写,它是一种运行时编译器)

持续测试和监控:在调整参数后,需要持续测试应用并监控其性能,以确保调优取得预期效果。

怎么调:

1、堆内存设置(比如-Xms和-Xmx参数设置初始和最大堆内存)。
2、新生代和老年代的大小比例(使用-XX:NewRatio)。
3、垃圾收集器选择和调整
(比如-XX:+UseG1GC,-XX:+UseConcMarkSweepGC)。
4、垃圾收集细节调整
(如设置线程数量-XX:ConcGCThreads,年轻代大小-XX:NewSize等)。
5、JVM堆栈大小(如-Xss设置每个线程的堆栈大小)。
6、逃逸分析和内联优化(如-XX:+DoEscapeAnalysis启用逃逸分析优化)。

为了解决什么问题:

1、减少垃圾收集的频率和暂停时间,避免影响到用户体验。
2、防止内存泄漏和内存溢出。
3、提高吞吐量,确保程序可以在短时间内处理更多的工作负载。
4、控制资源消耗,防止应用消耗过多的系统资源。

正常情况下需要调吗:

在许多情况下,JVM默认参数可以适用于标准应用程序,不需要特别的调优。
但对于有特定性能目标或在资源使用上有特定限制的重要应用程序,JVM调优是必要的。
例如,对于大规模的、内存密集型的或者要求高实时性的应用程序,经过专业调优后通常会有显著的性能改进。

总之,JVM调优是一个持续的过程,需要基于实际运行数据不断优化。快速反应的监控和分析,以及在实际运行环境中测试和验证调优效果非常重要。

JVM垃圾收集器

提示:思想,仅仅是思想

区分垃圾

在JVM中垃圾回收的第一步是确认什么是垃圾,现代主流的JVM实现主要使用可达性分析算法来识别哪些对象是垃圾。引用计数法因为循环引用等问题在Java虚拟机中并未广泛采用。

收集方式

垃圾收集的区域划分:

1、新生代(Young Generation)收集:收集新创建的对象,这些对象大多是短命的。
2、老年代(Old Generation/Tenured Space)收集:收集长时间存活的对象。
3、永久代(PermGen):在Java 8之前的版本中,存放类信息和常量。Java 8及之后,被**元空间(Metaspace)**所取代。
4、全部空间收集:也称为Full GC,会涉及新生代、老年代以及元空间(如果使用的是Java 8+版本)的收集。

按照收集垃圾的线程数量划分:

单线程收集:使用单个线程执行垃圾回收,这可能会导致较长的暂停时间,主要见于旧式或者简单的垃圾收集器中。
多线程收集:使用多个线程并发执行垃圾回收,以减少暂停时间和提高垃圾回收效率,现代垃圾收集器通常采用多线程。

对空间的利用率划分:

标记-清除(Mark-Sweep):标记所有可达对象,然后清除未被标记的对象,这种方法会产生内存碎片。
标记-整理(Mark-Compact):标记所有可达对象,然后将活动对象移向内存的一端,清理掉未被移动的部分,这种方法减少了内存碎片。
复制(Copying):将内存分为两块,每次只使用一块。垃圾收集时,将活动对象复制到未被使用的另一块内存区域,然后清除原有的那块内存区域中所有对象。

具体的垃圾收集器:每种垃圾收集器的实现通常采用多种上述策略的组合,针对不同的场景和需求进行优化,如:
1、Serial Collector:一个单线程收集器,适用于小型堆。
2、Parallel Collector:一个多线程收集器,也被称作“Throughput Collector”,适用于中到大型堆。
3、CMS (Concurrent Mark Sweep) Collector:以获取最短回收停顿时间为目标的收集器。
4、G1 (Garbage-First) Collector:适用于大型堆,期望可预测的停顿时间。
5、ZGC (Z Garbage Collector) 和 Shenandoah:为了减少停顿时间到极致而设计的收集器,它们使用了不同的技术实现极低的停顿时间。

垃圾收集器详细介绍:

新生代收集器:

  1. Serial收集器:

    • 算法:复制算法
    • 优点:简单高效,适用于单线程小型应用
    • 缺点:停顿时间较长
    • 默认区域:新生代
  2. ParNew收集器:

    • 算法:复制算法
    • 优点:多线程并行收集,适用于多核CPU环境
    • 缺点:停顿时间较长
    • 默认区域:新生代

老年代收集器:

  1. Serial Old收集器:

    • 算法:标记-整理算法
    • 优点:简单高效,适用于单线程小型应用
    • 缺点:停顿时间较长
    • 默认区域:老年代
  2. Parallel Old收集器:

    • 算法:标记-整理算法
    • 优点:多线程并行收集,适用于多核CPU环境
    • 缺点:停顿时间较长
    • 默认区域:老年代

整堆收集器:

  1. CMS (Concurrent Mark Sweep)收集器:

    • 算法:标记-清除算法
    • 优点:并发收集,停顿时间短
    • 缺点:产生碎片,无法处理浮动垃圾,CPU资源敏感
    • 默认区域:老年代
    • JDK版本:JDK 1.4至JDK 8
  2. G1 (Garbage-First)收集器:

    • 算法:分代收集算法,包括复制算法和标记-整理算法
    • 优点:整体吞吐量高,可控制停顿时间
    • 缺点:运行时开销较大
    • 默认区域:整个堆空间
    • JDK版本:JDK 9及以后

其他收集器:

  1. Shenandoah收集器:

    • 算法:并发标记-压缩算法
    • 优点:极低的停顿时间,适用于大堆、低延迟的应用
    • 缺点:运行时开销较大
    • 默认区域:整个堆空间
    • JDK版本:JDK 12及以后
  2. ZGC (Z Garbage Collector)收集器:

    • 算法:并发压缩算法
    • 优点:极短的停顿时间,适用于大堆、低延迟的应用
    • 缺点:运行时开销较大
    • 默认区域:整个堆空间
    • JDK版本:JDK 11及以后

小结

提示:未完成
这个文章其实并未完成,这里还有一些关于JVM中的数据怎么去可视化,怎么去分析数据性能,异常之后怎么去操作如:OOM之后等等
后续会补上。并在完善当前文章

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>