性能优化专题(JVM垃圾回收)

文章目录

    • eden
    • survivor
    • 老年代
    • 回收
      • 方法论
        • 标记-清除算法
        • 复制回收算法
        • 标记-整理算法
      • 垃圾收集器
        • Serial
        • ParNew
        • Parallel Scavenge(全局)
        • Serial Old
        • Parallel Old
        • CMS(并行清理)
        • G1(用的少)
      • 回收的时间节点

eden

-Xms20m -----starting开始的大小即最小
-Xmx200m -----max最大空间
-Xmn20m -----new(新生代的大小)
-XX:(Boolean类型)DisableExplicitGC

  • -XX:-DisableExplicitGC代表关闭
  • -XX:+DisableExplicitGC代表开启

-XX:preBlockSpin=10(数值类型)
Thread Locale Allaction Buffer TLAB

首先申请空间的时候会去eden区去申请,那是不是所有的对象都在eden区分配?答案不是的,大部分对象还有栈上分配都是在eden分配,大对象是直接进入到老年代的,优先去eden去分配空间,最后还是在堆里面分配。

对象去分配的时候,内存规整(持有压缩算法)的话,把对象的地址给指向
性能优化专题(JVM垃圾回收)_第1张图片再继续申请空间的话,性能优化专题(JVM垃圾回收)_第2张图片继续移动指针(指针碰撞)。在操作空间的时候会是多个线程操作共享空间,性能优化专题(JVM垃圾回收)_第3张图片比如这样,就涉及到了一个同步的问题,jvm中用CAS来解决指针激烈碰撞同步问题,二者对象是不会并行存在的性能优化专题(JVM垃圾回收)_第4张图片这样非常消耗资源的所以开辟了另外一种栈上分配来解决。
在堆里面每个线程都有一个属于自己的TLAB(Thread Local Allcation Buffer)即线程本地分配缓存区。这是一个线程专用的内存分配区域。性能优化专题(JVM垃圾回收)_第5张图片
如果要分配空间的话,只需要在这个线程单独的空间栈上分配,这样就不存在并发性能优化专题(JVM垃圾回收)_第6张图片
-XX:+UseTLAB
如果内存不规整的话性能优化专题(JVM垃圾回收)_第7张图片
则会FreeList来标记哪些空间是空闲的相关详细信息。
多线程情况下,会存在并发,用cas会影响效率,所以jvm还是采用栈上分配的形式来避免过多的这种消耗资源的操作。

survivor

性能优化专题(JVM垃圾回收)_第8张图片
每一个对象的分配都会在eden区,形式或许有很多种,s0和s1是survivor区,即当eden快满的时候将会触发一次minorGC,通过复制回收算法,不能回收的移到s0区中
对象分配eden
-XX:SurvivorRatio=8
8:1:1的分区:因为对象的生命周期不一样,希望对象能最大限度的不要进入老年代,让其生命周期age能限度的更大,不影响到我们的使用,新生代使用的是MinorGC,而老年代使用的是MajorGC。效率上比MinorGC要慢很多

老年代

大对象
设置该参数决定我们要不要直接进入老年代。单位是B
-XX:PretenureSizeThreshold=3145728
在这里插入图片描述
让其直接进入老年代
长期存活的对象
控制条件-XX:MaxTenuringThreshold=15(默认年龄)
age大于多少的时候就可以进入老年代
动态对象年龄判定
相同年龄所有对象的大小总和 > Survivor空间的一半
空间分配担保机制
新生代的Minor GC之前检查
老年代最大可用连续空间是否 > 新生代所有对象总空间

Minor GC:新生代回收算法
Major GC:老年代回收算法
Full GC:Minor GC + Major GC
垃圾回收器的最终目的是为了减少Ful GC

引用


  • – Object obj = new Object() 判断算法,GC Root可达

  • –内存不足的时候会被回收掉SoftReference,可做缓存使用

  • – 不管空间够不够用,就回收

  • – 弱引用的基础上在引用的时候会被通知到

回收

方法论

算法是演变的过程

标记-清除算法

使用过后的进行标记,清除掉标记的空间
性能优化专题(JVM垃圾回收)_第9张图片
其效率不高,空间碎片多

复制回收算法

优点实现简单,高效。
缺点空间利用率低
性能优化专题(JVM垃圾回收)_第10张图片

标记-整理算法

性能优化专题(JVM垃圾回收)_第11张图片
如果两个都存活,会进行整理,这样没有碎片的存在。
根据其理论基础,会有不同的垃圾回收器

垃圾收集器

性能优化专题(JVM垃圾回收)_第12张图片

新生代用的是复制回收算法
性能优化专题(JVM垃圾回收)_第13张图片

Serial

站在椅子上不要动还是边动我边打扫。这里是站在椅子上不要动
性能优化专题(JVM垃圾回收)_第14张图片
单线程GC处理垃圾回收,用于我们的新生代

ParNew

多个线程处理GC垃圾回收,相较于Serial是多了线程。处理速率更快。用于新生代。
多线程的个数
-XX:ParallelGCThreads=n

Parallel Scavenge(全局)

面向的是吞吐量
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
关于的是时间上的全局分布。
-XX:MaxGCPauseMillis=n 控制GC的停止时间
-XX:GCTimeRatio=n
-XX:UseAdaptiveSizePolicy

Serial Old

标记整理算法
可以和任何一个新生代产生关联,默认是Serial
Cms备用预案 Concurrent Mode Failure时使用

Parallel Old

标记整理算法
只和Parallel Scavenge结合使用

CMS(并行清理)

常用
标记清除算法
默认的新生代处理器是ParNew
目标是减少回收停顿时间
除了CMS之外,其他所有算法都会整理压缩。
初始标记,STW,标记在GCRoot的一个表(GCRoot直接关联),单线程
并发标记,线程在运行的时候,业务线程也在运行。根据Root去跟踪一下链
重新标记,STW(业务线程停止),并发的往前走,第二阶段的时候业务线程在进行,关系可能产生改变。多线程。
并发清除, 开启用户线程,同时GC线程开始对为标记的区域做清扫。
劣:CPU敏感,吞吐量下降,碎片存在(压缩:-XX:CMSInitiationOccupancyFraction)
当到了某个阶段(Concurrent Mode Failure)就要启动Serial Old
性能优化专题(JVM垃圾回收)_第15张图片
在FullGc的时候要不要开启压缩-XX:+UseCMSCompactAtFullCollection
间隔FullGC之后压缩一次-XX:CMSFullGCBeforeCompaction 0表示每次都压
显示设置用什么回收算法-XX:+UseConcMarkSweep
性能优化专题(JVM垃圾回收)_第16张图片
性能优化专题(JVM垃圾回收)_第17张图片

G1(用的少)

把整个内存空间隔成n个块,每个块的大小1-32M,最多2000个区域

性能优化专题(JVM垃圾回收)_第18张图片
垃圾回收有两种:一种是Young GC 一种是Old GC
并发标记垃圾回收STW的时候,会有内存压缩的操作。
Garbage first(G1)会优先选择第一块垃圾最多的区域去收集

当一个线程抛出OOM异常后,它所占据的内存资源会全部被释放掉,从而不会影响其他线程的运行。

回收的时间节点

时间点称之为 “Stop The World”----Safepoint,这个时间点在程序中的选定要是太少,那么GC 就要等待太久,要是太多个安全点,那么GC 次数变多,容易引起性能问题,所以安全点的选定基本上是以“是否具有让程序长时间执行的特征”,具有这类的最明显的特征就是指令序列复用,例如方法调用,循环跳转,异常跳转等。
应该如何中断正在执行的线程,当要GC 时所有线程一起停下来吗?
JVM 使用主动式中断( Voluntary Suspension ),当要GC时,仅仅设置一个标志位,让线程自己去主动轮询这个标志,发现中断标志为真时,就自己挂起,轮徐标志的地方和安全点是重合的。

GC日志
1.输出日志
-XX:+PrintGCTimeStamps
-XX:PrintGCDetails
-Xloggc:/home/gc.log
-XX:PrintHeapAtGC
2.日志文件控制
-XX:-UseGCLogFileRotation
-XX:GCLogFileSize=8K
3.怎么看
jdk自带的监控工具
jmap -heap pid 堆的使用情况
jstat -gccause pid time jstat -gccause 256 3000 上一次gc执行的原因
jstack 线程dump
jvisualvm

你可能感兴趣的:(性能优化)