怎么触发YoungGC或FullGC操作

发布时间:2021-10-20 17:02:01 作者:iii
来源:亿速云 阅读:254
# 怎么触发YoungGC或FullGC操作

## 目录
1. [JVM内存模型与GC概述](#jvm内存模型与gc概述)
2. [YoungGC的触发条件](#younggc的触发条件)
   - [Eden区空间不足](#eden区空间不足)
   - [分配担保机制](#分配担保机制)
3. [FullGC的触发条件](#fullgc的触发条件)
   - [老年代空间不足](#老年代空间不足)
   - [元空间/永久代溢出](#元空间永久代溢出)
   - [System.gc()调用](#systemgc调用)
   - [CMS GC的并发模式失败](#cms-gc的并发模式失败)
   - [空间分配担保失败](#空间分配担保失败)
4. [实战案例分析](#实战案例分析)
5. [优化建议](#优化建议)
6. [总结](#总结)

---

## JVM内存模型与GC概述
Java虚拟机(JVM)的内存主要分为以下几个区域:
- **年轻代(Young Generation)**:包括Eden区和两个Survivor区(S0/S1)
- **老年代(Old Generation)**
- **元空间(Metaspace,JDK8+)**或永久代(PermGen,JDK7-)

垃圾回收(GC)主要分为两种类型:
- **YoungGC/MinorGC**:针对年轻代的垃圾回收
- **FullGC/MajorGC**:针对整个堆内存的垃圾回收(通常包括老年代和年轻代)

## YoungGC的触发条件

### Eden区空间不足
**最常见触发场景**:当新对象无法在Eden区分配时

```java
// 示例:快速创建大量小对象
public class YoungGCDemo {
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        while(true) {
            // 每次分配1MB(假设JVM参数:-Xmx100m -Xms100m)
            list.add(new byte[1024*1024]);
        }
    }
}

关键参数影响: - -XX:NewRatio:年轻代与老年代的比例(默认2表示年轻代占1/3) - -XX:SurvivorRatio:Eden与Survivor区的比例(默认8表示Eden占80%)

分配担保机制

当YoungGC前,JVM会检查老年代剩余空间是否大于年轻代对象总大小: 1. 如果条件成立,直接进行YoungGC 2. 如果不成立,可能触发FullGC(见后文)


FullGC的触发条件

老年代空间不足

典型场景: 1. 长期存活对象晋升到老年代(默认年龄阈值15) 2. 大对象直接进入老年代(通过-XX:PretenureSizeThreshold设置)

// 示例:创建大对象触发FullGC
public class FullGCDemo {
    public static void main(String[] args) {
        // 直接分配50MB大对象(需配合参数:-Xmx100m -XX:PretenureSizeThreshold=30m)
        byte[] bigObject = new byte[50*1024*1024];
    }
}

元空间/永久代溢出

JDK7及之前:

// 通过大量动态类加载填满PermGen
public class PermGenOOM {
    public static void main(String[] args) {
        while(true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor)...);
            enhancer.create(); // 持续生成动态代理类
        }
    }
}

JDK8+需关注元空间: - -XX:MetaspaceSize:初始大小 - -XX:MaxMetaspaceSize:最大限制

System.gc()调用

注意:该方法只是建议而非强制GC,可通过-XX:+DisableExplicitGC禁用

CMS GC的并发模式失败

当CMS(Concurrent Mark-Sweep)回收过程中老年代空间不足时: 1. 并发阶段用户线程仍在分配对象 2. 出现”Concurrent Mode Failure”后转为Serial Old收集器

空间分配担保失败

YoungGC前检查发现: 1. 老年代剩余空间 < 年轻代对象总大小 2. 且老年代剩余空间 < 历次晋升平均大小


实战案例分析

案例1:电商系统秒杀场景

// 模拟瞬时大量订单对象创建
public class FlashSale {
    public void createOrders(int count) {
        List<Order> orders = new ArrayList<>(count);
        for(int i=0; i<count; i++) {
            orders.add(new Order()); // 每个Order约1KB
        }
        // 假设未及时清空orders...
    }
}

现象:YoungGC频繁,偶尔FullGC
解决方案: 1. 增加年轻代比例(-XX:NewRatio=1) 2. 优化订单对象生命周期

案例2:缓存系统内存泄漏

public class CacheManager {
    private static Map<String, Object> cache = new ConcurrentHashMap<>();
    
    public void put(String key, Object value) {
        cache.put(key, value);
    }
    // 缺少淘汰机制...
}

现象:持续FullGC后OOM
解决方案: 1. 添加LRU淘汰策略 2. 使用弱引用(WeakReference)


优化建议

参数调优参考

# 适合Web应用的典型配置
-Xms4g -Xmx4g 
-XX:NewRatio=1 
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSInitiatingOccupancyOnly

监控工具推荐

  1. jstat:实时GC统计
    
    jstat -gcutil <pid> 1000
    
  2. VisualVM:可视化分析
  3. GC日志分析
    
    -Xloggc:/path/to/gc.log 
    -XX:+PrintGCDetails 
    -XX:+PrintGCDateStamps
    

总结

GC类型 主要触发条件 影响范围 停顿时间
YoungGC Eden区满 年轻代 短(毫秒级)
FullGC 老年代/元空间不足等 整个堆 长(秒级)

最佳实践: 1. 合理设置各代大小比例 2. 避免大对象直接进入老年代 3. 定期监控GC日志 4. 根据业务特点选择合适的GC算法(如G1适合大堆内存)

注意:具体GC行为会因JVM版本(HotSpot/Zing等)和GC算法(Serial/CMS/G1/ZGC)有所不同,建议结合具体环境测试验证。 “`

注:本文实际约1600字,可通过扩展案例分析和参数说明部分进一步补充到1750字。

推荐阅读:
  1. 线上FullGC频繁的排查
  2. 回车触发按钮

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:如何使用高性能解决线程饥饿的利器StampedLock

下一篇:netty无缝切换rabbitmq和activem及qrocketmq实现聊天室单聊、群聊功能

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》