jvm-05

  • 垃圾收集发生的时机
    • GC是由JVM自动完成的,根据JVM系统环境而定,所以时机是不确定的。 当然,我们可以手动进行垃圾回收,
      比如调用System.gc()方法通知JVM进行一次垃圾回收,但是具体什么时刻运行也无法控制。也就是说
      System.gc()只是通知要回收,什么时候回收由JVM决定。 但是不建议手动调用该方法,因为消耗的资源比较
      大。
    • 一般以下几种情况会发生垃圾回收
    • Full GC = Minor GC+Major GC +MetaSpace GC
      • 当Eden区或者S区不够用
      • 老年代空间不够用
      • 方法区空间不够用了
      • System.gc()
GC日志文件分析工具
  • gceasy
    • https://gceasy.io
    • 可以比較不同的垃圾收集器的吞吐量和停顿时间
    • 比如打开cms-gc.log和g1-gc.log
  • GCViewer
调优
  • 是否选用G1垃圾收集器的判断依据
  • https://docs.oracle.com/javase/8/docs/technotes/guides/vm/G1.html#use_cases
  • 50%以上的堆被存活对象占用
  • 对象分配和晋升的速度变化非常大
  • 垃圾回收时间比较长
调优步骤
  • 使用G1GC垃圾收集器: -XX:+UseG1GC
    • 修改配置参数,获取到gc日志,使用GCViewer分析吞吐量和响应时间
    Throughput Min Pause Max Pause Avg Pause GC count 99.16% 0.00016s 0.0137s 0.00559s 12
    
  • 调整内存大小再获取gc日志分析
-XX:MetaspaceSize=100M
-Xms300M
-Xmx300M

设置堆内存大小后,获取gc日志,使用GCViewer分析吞吐量和响应时间

Throughput Min Pause Max Pause Avg Pause GC count 98.89% 0.00021s 0.01531s 0.00538s 12
  • 调整最大停顿时间
-XX:MaxGCPauseMillis=20 设置最大GC停顿时间指标
Throughput Min Pause Max Pause Avg Pause GC count 98.96% 0.00015s 0.01737s 0.00574s 12
  • 启动并发GC时堆内存占用百分比
-XX:InitiatingHeapOccupancyPercent=45 G1用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的 使用比例。值为 0 则表示“一直执行GC循环)'. 默认值为 45 (例如, 全部的 45% 或者使用了45%).

获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput Min Pause Max Pause Avg Pause GC count 98.11% 0.00406s 0.00532s 0.00469s 12
官网建议

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#recommendations

  • 不要手动设置新生代和老年代的大小,只要设置整个堆的大小
    G1收集器在运行过程中,会自己调整新生代和老年代的大小 其实是通过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标 如果手动设置了大小就意味着放弃了G1的自动调优
    
    • 好处:吞吐量增减,GC次数减少
    • 不好: 停顿时间变大–>Client较长时间停顿。原因:每一次垃圾回收的时候,周期就会拉长。
  • 不断调优暂停时间目标(停顿时间不要太严格)
一般情况下这个值设置到100ms或者200ms都是可以的(不同情况下会不一样),但如果设置成50ms就不太合理。暂停 时间设置的太短,就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续 的过程,逐步调整到最佳状态。暂停时间只是一个目标,并不能总是得到满足。

优势:停顿时间能够被控制了
劣势:GC次数增加了(原因:一次回收或标志没有标志完,只能下一次回收,下一次还没来得及回收或标志 再等下一次)

  • 使用-XX:ConcGCThreads=n来增加标记线程的数量
IHOP如果阀值设置过高,可能会遇到转移失败的风险,比如对象进行转移时空间不足。如果阀值设置过低,就会使标 记周期运行过于频繁,并且有可能混合收集期回收不到空间。 IHOP值如果设置合理,但是在并发周期时间过长时,可以尝试增加并发线程数,调高ConcGCThreads。
  • MixedGC调优

    • -XX:InitiatingHeapOccupancyPercent (堆内存使用占比,即达到某个百分比才触发回收)
    • -XX:G1MixedGCLiveThresholdPercent
    • -XX:G1MixedGCCountTarger
    • -XX:G1OldCSetRegionThresholdPercent
  • 适当增加堆内存大小

G1 和cms的区别
  • cms:老年代
    • 整体上使用标志- 清除法,空间碎片
  • G1:适用新生代和老年代
    • Regon,对堆内存进行逻辑分区
    • 标志-整理,减少空间碎片
    • 1 收集方式:Garbage First,优先会收集垃圾比较多的区域
    • 2 CMS:新生代,或者是老年代Card Table 引用了谁【不用全盘扫描整个老年代】,G1,Remembered Set Rset(谁引用了我,也不用全盘扫描,方式不一样)
    • 3 G1设计的初衷:以前的垃圾收集器:1必须扫描老年代,新生代和老年代 空间连续
    • 4 G1 产生:多核,大内存
    • 5 G1停顿时间
    • 6 CSet:一组被回收的分区的集合,存活对象移动到另外的分区 CSet <1%
如果Full GC频繁怎么办?怎样减少Full GC?
  • Young:Old Young适当增加,每一秒都产生大量对象,不让他过去老年代
GC的次数频繁,你会怎么办
  • 为什么会频繁?GC次数多,CPU使用率高了
    • 打印出gc 日志–>minor gc/major gc?,结合工具看
    • 内存空间少了?适当增加对内存空间
    • 选择垃圾收集器不合适、如果是是大内存的空间,可以选择G1
    • 是否是set pause time strict/堆内存使用了 occupancy(启动并发GC时堆内存占用百分比) 停顿时间过于严格
cup 持续飙升
  • 为什么CPU升高
  • top 看进程id,jstack/jinfo/jmap
    • 并发量太高?
      • 集群
      • mq
      • 业务层面 死锁?
oom
  • dump文件
  • 分析dump文件工具/MAT/其他工具
内存泄漏和内存溢出oom区别
  • 内存泄漏:内存得不到有效回收
  • 累计一定程度的内存泄漏对象导致 oom
方法区的回收主要是回收什么内容
  • 方法区里面存储的内容 是,类信息,静态变量,常量等
  • 没有用的类的信息、常量
  • 类信息什么时候能够被回收?:
    • 1 堆里面不再有该类对象
    • 2 加载该类的ClassLoader已经被回收了
    • 3 java.lang.Class对象也不再有任何地方引用了,反射也不能使用
    • 满足上述条件可以回收,不一定一定回收
不可达的对象一定就被回收吗?
  • 不可达对象—>finalize()---->可以变成 不是垃圾的对象
Young GC 会stop the world吗
  • YoungGC:新生代的GC
    • 不管什么 GC,都会有 stop-the-world,只是发生时间的长短
[23-05-29 20:39:13.243] {main} <proxy-cache> requires Resin Professional. Please see http://www.caucho.com for Resin Professional information and licensing. [23-05-29 20:39:13.400] {main} [23-05-29 20:39:13.400] {main} Resin-4.0.58 (built Fri, 24 Aug 2018 01:23:14 PDT) [23-05-29 20:39:13.401] {main} [23-05-29 20:39:13.402] {main} Windows 10 10.0 amd64 [23-05-29 20:39:13.402] {main} Java(TM) SE Runtime Environment 1.8.0_191-b12, GBK, zh [23-05-29 20:39:13.402] {main} Java HotSpot(TM) 64-Bit Server VM 25.191-b12, 64, mixed mode, Oracle Corporation [23-05-29 20:39:13.402] {main} [23-05-29 20:39:13.403] {main} user.name = WR182 [23-05-29 20:39:13.541] {main} [23-05-29 20:39:13.546] {main} server listening to 127.0.0.1:6800 [23-05-29 20:39:13.549] {main} [23-05-29 20:39:13.766] {main} Table[mnode:2,D:\WEAVER\Resin\resin-data\app-0\distcache\mnode.db] validating indexes due to unclean shutdown. [23-05-29 20:39:13.816] {main} Table[data:3,D:\WEAVER\Resin\resin-data\app-0\distcache\data.db] validating indexes due to unclean shutdown. [23-05-29 20:39:13.942] {main} [23-05-29 20:39:13.943] {main} resin.home = D:\WEAVER\Resin [23-05-29 20:39:13.943] {main} resin.root = D:\WEAVER\Resin [23-05-29 20:39:13.943] {main} resin.conf = d:\WEAVER\Resin\conf\resin.xml [23-05-29 20:39:13.943] {main} [23-05-29 20:39:13.943] {main} server = 127.0.0.1:6800 (app:app-0) [23-05-29 20:39:13.943] {main} stage = production [23-05-29 20:41:38.003] {main} Found library 'resin_os' as 'd:\WEAVER\Resin\win64\resin_os.dll', but the load failed. The JVM exception was: java.lang.UnsatisfiedLinkError: no resin_os in java.library.path [23-05-29 20:42:40.782] {resin-60} WebApp[production/webapp/default/lib] active [23-05-29 20:42:40.782] {main} Host[production/host/default] active [23-05-29 20:42:40.782] {main} ServletService[id=app-0,cluster=app] active [23-05-29 20:42:40.782] {main} [23-05-29 20:42:40.782] {main} http listening to *:8080 [23-05-29 20:42:40.782] {main} https listening to *:8444 [23-05-29 20:42:40.796] {main} [23-05-29 20:42:40.796] {main} Resin[id=app-0] started in 210426ms Connected to server [23-05-29 20:43:29.233] {resin-55} WebApp[production/webapp/default/ROOT] active
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值