你知道的越多,不知道的就越多,业余的像一棵小草!

成功路上并不拥挤,因为坚持的人不多。

编辑:业余草

blog.csdn.net/qq_40378034

推荐:https://www.xttblog.com/?p=5221

前言

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

测试代码

public class MemoryRecycleTest {static volatile List<OOMobject> list = new ArrayList<>();public static void main(String[] args) {//指定要生产的对象大小为512Mint 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大小的对象
清理list.... 回收jvm内存....JVM内存已用的空间为:3 MB
JVM内存的空闲空间为:120 MB
JVM总内存空间为:123 MB
JVM总内存最大堆空间为:1979 MB

「VisualVM监控的堆内存情况」

VisualVM监控的堆内存情况

从图中堆内存的情况可以看出,在 JDK8 + CMS 的配置下,JVM 并不是立马归还内存给到操作系统,而是随着 FullGC 次数的增多逐渐归还,最终会全部归还

JDK8 G1

「JVM参数」

-Xms128M -Xmx2048M -XX:+UseG1GC

「VisualVM监控的堆内存情况」

VisualVM监控的堆内存情况

在 JDK8 + G1 的配置下,JVM 都是在每一次 FullGC 后全部归还物理内存。

JDK11 CMS

「JVM参数」

-Xms128M -Xmx2048M -XX:+UseConcMarkSweepGC

「VisualVM监控的堆内存情况」

VisualVM监控的堆内存情况

在 JDK11 + CMS 的配置下和 JDK8 + CMS 的情况相同(JVM 并不是立马归还内存给到操作系统,而是随着 FullGC 次数的增多逐渐归还,最终会全部归还)

JDK11 提供了一个 JVM 参数ShrinkHeapInSteps 。通过这个参数,可以在 GC 之后渐进式的归还内存给到操作系统。JDK11 下,此参数默认开启。可以把此参数关闭,看下堆内存的变化情况:

-Xms128M -Xmx2048M -XX:+UseConcMarkSweepGC -XX:-ShrinkHeapInSteps

「VisualVM监控的堆内存情况」

VisualVM监控的堆内存情况

在 JDK11 + CMS 的配置下,关闭ShrinkHeapInSteps参数后,JVM 都是在每一次 FullGC 后全部归还物理内存。

JDK11 G1

由于 JDK11 默认使用的是 G1 垃圾回收器,所以这里只设置了初始堆内存和最大堆内存。

「JVM参数」

-Xms128M -Xmx2048M

「VisualVM监控的堆内存情况」

VisualVM监控的堆内存情况
  1. JDK11 默认的ShrinkHeapInSteps是默认开启的,但这里看堆内存变化并不是渐进的缩小的。所以在 G1 回收器下,ShrinkHeapInSteps是无效的。如果我们手动关闭ShrinkHeapInSteps参数,发现堆内存变化和上面这个类似

  2. JDK11 下的 G1 和 JDK8 下的 G1 对内存的响应是不一样的。从堆内存变化来看, 「JDK11 下 G1 更加倾向于尽可能的利用内存,不着急回收」。而 JDK8 下 G1 则是倾向于尽可能的先回收内存。从图中看,JDK8 下 G1 的实际使用的堆内存大小基本是 JDK11 下 G1 的一半。

小结

如果代码保持不变,但是JVM参数中设置Xms和Xmx相同的话,不管是否有FullGC,堆内存大小都不发生变化,也就不释放内存给操作系统

GC 后如何归还内存给操作系统:

  • 能不能归还,主要依赖于 Xms 和 Xmx 是否相等

  • 何时归还,主要依赖于 JDK 版本和垃圾回收器类型

只有 FullGC 的时候才能真正触发堆内存收缩归还 OS。YGC 是不能使 JVM 主动归还内存给操作系统的。

尽量保持 Xms 和 Xmx 一致,这样可以减少堆内存调整带来的性能损耗,也可以减少堆内存调整带来的无内存风险。

参考:

  • https://segmentfault.com/a/1190000019856974

  • https://www.cnblogs.com/androidsuperman/p/11743103.html

  • http://blog.dutycode.com

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

  1. java一个接口执行结束释放内存_java的灵魂--JVM虚拟机

    JVM是运行在操作系统之上的,它与硬件没有直接的交互 JVM体系结构 1.类加载器 负责加载class文件,class文件在文件开头有特定的文件标示, 并且ClassLoader只负责class文件的 ...

  2. java程序启动后就进行了7次younggc_程序员如何优化 Java GC

    本文由CrowHawk翻译 Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇<How to Tune Java ...

  3. 深入理解java虚拟机gc_jvm GC收集器与内存分配(深入理解java虚拟机第三章)

    jvm GC收集器与内存分配(深入理解java虚拟机第三章) 本篇是<深入理解java虚拟机第三章>的笔记记录. 一 为什么要关注GC和内存分配? 需要排查各种内存溢出.内存泄漏问题时,或 ...

  4. java查看gc日志_GC日志查看

    GC日志查看 可以通过在java命令种加入参数来指定对应的gc类型,打印gc日志信息并输出至文件等策略. GC的日志是以替换的方式(>)写入的,而不是追加(>>),如果下次写入到同一 ...

  5. JAVA垃圾回收器源码_浅谈关于Java的GC垃圾回收器的一些基本概念

    一.基本回收算法 1. 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此 ...

  6. 卧槽!终于知道涛哥我为啥赚不到钱了

    前几天和一个Java公众号头部大佬D在微信上面聊天,大佬说周末有时间约下一起聊聊,向我请教下,我以为只是一句客套话也没在意,因为一来他的公众号比我做的好,粉丝量比我多很多,其次他也有团队合作. 结果周 ...

  7. 跟涛哥一起学嵌入式 25:我接触过近50块嵌入式开发板,分享一下教训和总结...

    最近老是有学员问我:涛哥,你的嵌入式教程针对哪款开发板鸭?到底使用哪款开发板学习?我的回答往往是:暂时不用开发板,学习嵌入式,不一定非得用开发板,在qemu仿真平台上学习就可以了.3年前我发布了互联网 ...

  8. Python爬虫从入门到精通:(41)JS逆向_RSA加密,Steam加密逆向_Python涛哥

    RSA加密: RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用. 非对称加密算法: 非对称加密算法需要两个密钥: 公开密钥(publickey:简称公钥) 私有密钥(pr ...

  9. Python爬虫从入门到精通:(43)JS逆向:完美世界RAS逆向_Python涛哥

    完美世界有很多游戏,比较出名的就是诛仙.魔兽世界等.完美今天就来看下完美世界登陆的逆向分析! JS逆向解析 登陆的时候这里有个点击认证.没关系,完美先忽略它,直接点击.完美主要探讨密码的逆向方式. 抓 ...

最新文章

  1. 杭电oj1176,2084java实现
  2. 【DSP开发】【VS开发】YUV与RGB格式转换
  3. ImportError: cannot import name cbook
  4. android 设计qq界面,[考试求助]仿照腾讯QQ应用软件,编写Android程序,登录界面设计...
  5. hadoop关键进程
  6. WINDOWS XP SP2 NTFS EFS加密文件的解密案例
  7. 如何处理VMware启动虚拟机时的错误信息Failed to lock the file
  8. Windows消息队列一
  9. ZZULIOJ 1090: 整数幂(多实例测试)
  10. 星辰网址缩短源码支持二维码
  11. Python 下载哔哩哔哩视频
  12. IP-SAN和FC-SAN存储的区别
  13. 媒体应用视频超分AI神器!360P视频一键转换HD
  14. 令代码停止_那些令人困惑的灯泡代码是什么意思?
  15. 夜神模拟器 android mprop 开启 ro.debuggable
  16. Window10 WiFi列表不显示解决方案
  17. Unity | Unity中UI框架的实现与使用
  18. Zuul网关的快速使用
  19. DELL(i7版本)麦克风杂音问题解决方案
  20. 小皮php的简单使用

热门文章

  1. 《Accurate eye center localisation by means of gradients》论文阅读
  2. 2016在电影院看过的电影
  3. 阿里云联合浙江大学举办首届数智服务创新挑战赛!
  4. 计算机的二三事——软件篇
  5. Deepin 系统安装NVIDIA
  6. “跨次元”检测模型hold住各种画风,真人赛博,在线Demo可玩
  7. 集成支付宝,跳转到支付宝后显示的不是支付页面
  8. 学习笔记(15):C++编程FFMpeg(QT5+OpenCV)实战--实时美颜直播推流-opencv播放rtsp海康摄像头和播放系统摄像头...
  9. 2017年ACM第八届山东省赛I题: Parity check(判断 第n项斐波那契数列奇偶性)
  10. 克劳士比语录(转载)