JVM性能调优理论与实践

内存模型

方法区,堆是所有线程共有。

栈,本地计数器是线程私有。JVM性能调优理论与实践_第1张图片

方法区

保存class文件加载后的类信息,常量池数据等

1.8后叫metaspace

会OOM,如动态加载类文件时: java.lang.OutOfMemoryError: PermGen space

JVM性能调优理论与实践_第2张图片

最大的内存区域,所有线程共享,保存对象和数组。

所有对象都存在堆中吗?

永久代并不属于堆内存中的一部分,jdk1.8之后永久代。

会OOM: java.lang.OutOfMemoryError: Java heap space

JVM性能调优理论与实践_第3张图片

虚拟机栈

各个线程私有

保存栈帧

栈帧:每个方法被执行的时候创建,用于存储局部变量表(包括参数)、操作栈、方法出口等信息。

会栈溢出:java.lang.StackOverflowError

会OOM: JVM实现支持动态扩展时会,HotSpot不支持,不会OOM

JVM性能调优理论与实践_第4张图片

本地方法栈

  • 保存native方法栈帧

  • 会栈溢出

  • 会OOM

程序计数器

  • 各个线程私有

  • 记录正在执行的JVM字节码指令位置

  • native方法执行时为空

  • 不会OOM

堆外内存

垃圾收集

CMS

  • 标记-清理:标记出垃圾对象,清除垃圾对象

  • 并发收集和清理,停顿较低,碎片多。

G1

  • jdk1.9默认的回收器

  • 控制回收时间:控制回收垃圾的时间,选择回收成本最低的Regions作为回收目标,达到实时收集的目的

  • 空间整理:空间碎片较少,有效的使用了连续空间,不会导致连续空间不足提前造成GC的触发

  • 内存拆分:把内存拆分成多等份(Region),逻辑上存在新生代和老年代的概念,无严格区分

 JVM性能调优理论与实践_第5张图片

什么情况下应该考虑使用G1
  • 实时数据占用超过一半的堆空间

  • 对象分配或者晋升的速度变化大

  • 希望消除长时间的GC停顿(超过0.5-1秒)

区别

  • 使用范围不同

    • CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用

    • G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用

  • STW的时间

    • CMS收集器以最小的停顿时间为目标的收集器。

    • G1收集器可预测垃圾回收的停顿时间(建立可预测的停顿时间模型)

  • 垃圾碎片

    • CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片。

    • G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。

  • 回收过程JVM性能调优理论与实践_第6张图片

方法与步骤

JVM内存调优主要目标是减少GC频率和耗时。GC包括以下几种

Minor GC:又叫young gc, 年轻代垃圾回收,主要采用复制清理算法。G1 GC也有youngGC

Full GC:又叫Major GC, old GC

监控工具

主要关注GC次数,GC耗时,线程数曲线,内存晋升分配,内存各区域折线

JVM性能调优理论与实践_第7张图片

内存

jmap命令

jmap -heap pid //堆及新生代内存占用 
jmap -histo pid | jmap -histo:live pid //查看对象个数及大小 
jmap -dump:format=b,file=heap.hprof pid //导出内存文件 
jmap -dump:live,format=b,file=heapLive.hprof pid//只导出存活的对象

内存dump:Java 线程&内存在线分析 说明文档 

内存分析:VisualVM 或者 JProfiler

JVM性能调优理论与实践_第8张图片

线程

  jtack命令

线程状态
线程动作
调用修饰

参考jstack — 查看堆栈信息

jstack -l pid//查看线程状态,打印锁相关日志。 有死锁会打印:Found one Java-level:deadlock

 
  

top -Hp pid //查看某个进程内各个线程的CPU占用。 jstack pid>thread.txt //dump线程信息到文本文件中。JVM性能调优理论与实践_第9张图片

  • NEW :线程创建未启动,不会出现在Dump中。

  • RUNNABLE:运行状态。

  • BLOCKED:受阻塞状态并等待监视器锁。

  • WAITING:无限期等待另一个线程执行特定操作。

  • TIMED_WAITING:有时限的等待另一个线程的特定操作。

  • TERMINATED:已退出的状态。

  • runnable:状态一般为RUNNABLE。

  • in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。

  • waiting for monitor entry:进入区等待,状态为BLOCKED。

  • waiting on condition:等待区等待、被park。

  • sleeping:休眠的线程,调用了Thread.sleep()。

  • locked :使用synchronized申请对象加锁成功,成为监视器的拥有者。

  • waiting to lock :使用synchronized申请对象锁未成功,在进入区等待。

  • waiting on :使用synchronized申请对象锁成功后,释放锁幵在等待区等待。

  • parking to wait for 基本的线程阻塞原语,不通过监视器在对象上阻塞。和Concurrent包一起出现,如ReentrantLock

  1. 死锁分析

  2. CPU占用分析

top命令查到的线程号是10进制,jstack中打印的线程号是16进制,要把10进制转为16进制去查看

JVM性能调优理论与实践_第10张图片

JVM性能调优理论与实践_第11张图片

  1. GC

    1. GC日志开关

       

      -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintGCDetails

      1. PrintGC必须开启,只开启PrintGCDetails、PrintGCTimeStamps不会输出GC

    2. 查看是否开启GC日志打印

       

      admin@M-C02FXLJ1MD6M:~$ jinfo -flag PrintGC 11871 -XX:-PrintGC// 减号说明没有打开日志

    3. 动态设置GC开关: jinfo

          -flag pid:打印指定JVM的参数值

          -flag [+|-] pid:设置指定JVM参数的布尔值

          -flag = pid:设置指定JVM参数的值

     

    //打开GC开关 jinfo -flag +PrintGC 2345

    1. 分析GC日志

      JVM性能调优理论与实践_第12张图片

       JVM性能调优理论与实践_第13张图片

          GC分析工具:https://gceasy.io/gc-index.jsp

          内存泄露

  1. 标准

  • Minor GC执行耗时小于50ms;

  • Minor GC执行频率较低,小于10秒一次;

  • Full GC执行耗时小于1s;

  • Full GC执行频率较低,小于10分钟1次;

参数调优

参数类型

 
  

标准类型: -version -help。 各个JVM都会支持,一般不会变动 X参数:非标准参数(变动比较小),并且默认jvm实现这些参数的功能。如-Xcomp、-Xmixed。 XX参数:不稳定参数,各个JVM实现可能不同。 如-XX:+UseConcMarkSweepGC、-XX:+UseG1GC,-XX:MaxGCPauseMillis=500

内存

-Xms(memory start):初始堆大小,一般初始值可以和最大值设一样,避免GC后内存重新分配。

-Xmx(memory max):最大堆大小。

-Xmn(memory new):新生代大小。

-XX:NewRatio:新生代(Eden+2 survivor space)与老年代(除去持久代)的比值

线程

-Xss(stack size):每个线程的堆栈大小。

垃圾回收

-XX:MaxTenuringThreshold:年轻代最大年龄。

-XX:PretenureSizeThreshold:对象超过多大时直接在老年代分配,默认值0,单位字节。

-XX:ParallelGCThreads:并行收集器的线程数。

-XX:+DisableExplicitGC:禁止System.gc(),免得程序员误调用gc方法影响性能。

-XX:CMSFullGCsBeforeCompaction:CMS不对内存空间进行压缩、整理,这里配置多少次FullGC后进行内存压缩

-XX:+PrintGC

-XX:+PrintGCDetails

XX:+PrintGCApplicationStoppedTime:打印GC期间程序暂停时间

-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息

-Xloggc:filename:设置GC日志位置

G1

-XX:MaxGCPauseMillis:最大停顿时间。

不要设置-Xmn, -XX:NewRatio. G1会动态调整年轻代大小,以满足最大停顿时间。

-XX:G1HeapRegionSize = n 设置region大小

-XX:InitiatingHeapOccupancyPercent = 45 设置触发GC的堆占用百分比

-XX:G1NewSizePercent = 5 设置要用作年轻代大小的最小值的堆百分比。默认值为Java堆的5%

-XX:G1MaxNewSizePercent = 60 设置堆大小的百分比,以用作年轻代大小的最大值。默认值为Java堆的60%

你可能感兴趣的:(jvm,java,算法)