相关文章推荐
高大的拐杖  ·  Python空间数据可视化利器之Geopan ...·  2 年前    · 
坏坏的骆驼  ·  android 异步处理 android ...·  2 年前    · 
道上混的创口贴  ·  [错误] ...·  2 年前    · 
近视的包子  ·  Android读取视频metadata的拍摄 ...·  2 年前    · 
长情的刺猬  ·  学习数据库必须掌握的54条SQL查询语句 ...·  2 年前    · 
Code  ›  出大事了,涛哥你们Java应用GC后不释放内存开发者社区
list jvm 最大堆
https://cloud.tencent.com/developer/article/1912171
坚强的蘑菇
2 年前
作者头像
业余草
0 篇文章

出大事了,涛哥你们Java应用GC后不释放内存

前往专栏
腾讯云
备案 控制台
开发者社区
学习
实践
活动
专区
工具
TVP
文章/答案/技术大牛
写文章
社区首页 > 专栏 > 业余草 > 正文

出大事了,涛哥你们Java应用GC后不释放内存

发布 于 2021-12-06 17:40:00
2.1K 0
举报

前言

公司众多系统中有一个系统使用的是 CMS 垃圾回收器,JVM 初始堆内存不等于最大堆内存,但通过监控信息发现:在经过一次 FullGC 之后, 服务器 物理内存剩余空间并未提升, 运维 同事告诉我说,有内存泄露,因为 GC 了之后,内存并没有被释放。按照大部分人的理解,FullGC 之后 JVM 进程会释放的内存一部分还给物理内存,下面通过几个实验来对比验证一下 CMS 和 G1 的物理内存归还机制。

测试代码

public class MemoryRecycleTest {
    static volatile List<OOMobject> list = new ArrayList<>();
    public static void main(String[] args) {
        //指定要生产的对象大小为512M
        int count = 512;
        //新建一条线程,负责生产对象
        new Thread(() -> {
            try {
                for (int i = 1; i <= 10; i++) {
                    System.out.println(String.format("第%s次生产%s大小的对象", i, count));
                    addObject(list, count);
                    //休眠40秒
                    Thread.sleep(i * 10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
        }).start();
        //新建一条线程,负责清理List,回收JVM内存
        new Thread(() -> {
            for (; ; ) {
                //当List内存到达512M,就通知GC回收堆
                if (list.size() >= count) {
                    System.out.println("清理list.... 回收jvm内存....");
                    list.clear();
                    //通知GC回收
                    System.gc();
                    //打印堆内存信息
                    printJvmMemoryInfo();
        }).start();
        //阻止程序退出
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            e.printStackTrace();
    public static void addObject(List<OOMobject> list, int count) {
        for (int i = 0; i < count; i++) {
            OOMobject ooMobject = new OOMobject();
            //向List添加一个1M的对象
            list.add(ooMobject);
            try {
                //休眠100毫秒
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
    public static class OOMobject {
        //生成1M的对象
        private byte[] bytes = new byte[1024 * 1024];
    public static void printJvmMemoryInfo() {
        //虚拟机级内存情况查询
        long vmFree = 0;
        long vmUse = 0;
        long vmTotal = 0;
        long vmMax = 0;
        int byteToMb = 1024 * 1024;
        Runtime rt = Runtime.getRuntime();
        vmTotal = rt.totalMemory() / byteToMb;
        vmFree = rt.freeMemory() / byteToMb;
        vmMax = rt.maxMemory() / byteToMb;
        vmUse = vmTotal - vmFree;
        System.out.println("");
        System.out.println("JVM内存已用的空间为:" + vmUse + " MB");
        System.out.println("JVM内存的空闲空间为:" + vmFree + " MB");
        System.out.println("JVM总内存空间为:" + vmTotal + " MB");
        System.out.println("JVM总内存最大堆空间为:" + vmMax + " MB");
        System.out.println("");
}

JDK8 CMS

「JVM参数」 :

-Xms128M -Xmx2048M -XX:+UseConcMarkSweepGC

「控制台打印的内容」 :

第1次生产512大小的对象
清理list.... 回收jvm内存....
JVM内存已用的空间为:6 MB
JVM内存的空闲空间为:1202 MB
JVM总内存空间为:1208 MB
JVM总内存最大堆空间为:1979 MB
第2次生产512大小的对象
清理list.... 回收jvm内存....
JVM内存已用的空间为:3 MB
JVM内存的空闲空间为:1097 MB
JVM总内存空间为:1100 MB
JVM总内存最大堆空间为:1979 MB
第3次生产512大小的对象
清理list.... 回收jvm内存....
JVM内存已用的空间为:3 MB
JVM内存的空闲空间为:706 MB
JVM总内存空间为:709 MB
JVM总内存最大堆空间为:1979 MB
第4次生产512大小的对象
 
推荐文章
高大的拐杖  ·  Python空间数据可视化利器之Geopandas - 知乎
2 年前
坏坏的骆驼  ·  android 异步处理 android 异步网络请求_mob6454cc63af5e的技术博客_51CTO博客
2 年前
道上混的创口贴  ·  [错误] openpyxl.utils.exceptions.IllegalCharacterError - 知乎
2 年前
近视的包子  ·  Android读取视频metadata的拍摄时间(即首次创建时间)、读取文件的第一次creationTime(需要Api26及26+)_gmsl2的matadata的时间戳_舔狗的尊严的博客-CSDN博客
2 年前
长情的刺猬  ·  学习数据库必须掌握的54条SQL查询语句 - elleniou - 博客园
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号