JVM 垃圾收集与内存分配
判断对象是否还活着
引用计数法
给对象添加引用计数器,添加加1,引用失效减1,如果为0就是不可使用的。问题是不能解决互相引用带来的问题
可达性分析法
- 以GC Roots为起点,判断到一个对象是否有引用链,就是从开始节点向下能否搜索到,如果搜索不到就是不可达,可以被回收
- GC Roots有以下
- 虚拟机栈中的引用对象
- 方法区中的类静态属性的引用对象
- 方法区中的常量引用对象
本地方法栈是JNI(Native方法)的引用对象
什么是引用
- 就是reference类型中存储的数值代表另外一块内存中的起始地址就称这块内存代表着一个引用(侠义的引用)
- 强引用:类似Object obj=new Object()这类的,垃圾永不回收的引用对象 SoftReference
- 软引用:在内存发生溢出异常前,进行第二次回收的,如果回收后还不足,才会抛出溢出异常
- 弱引用: 能存活到下一次垃圾回收之前,与内存是否足够无关 WeakReference
虚引用:最弱唯一的目的就是在被回收时收到一个系统通知,不能通过引用获取对象和操作影响对象 PhantomReference
消除对象
一个对象至少要经历两次标记:如果不可达进行第一次标记并筛选是否要执行finalize()方法,当对象没有finalize()或被执行过都认为不需要执行。如果判断需要执行会把这个对象放在F-Queue队列中并在稍后虚拟机会以一个底线程去执行,所以这是对象自救的最后一次机会
回收方法区
- 判断一个类是否有用
- 类所有的实例都回收
- 加载类的ClassLoader已回收
- 对应的java.lang.Class对象没有任何地方被引用也无法通过反射访问该类的方法
是否回收类HotSpot虚拟机提供了-Xnoclassgc参数进行控制
垃圾回收算法
标记-清除法
- 标记阶段:慢
清除阶段 :慢,有内存碎片
复制算法
- 把内存一分为二(大小相等)当一块用完了,把存活的复制到另一块上
- 缺点:内存只用了一半:
优化:不分为相等的两部分而是分为Eden Survivor 默认比例8:1,当survivor不够时,老年代来担保,提醒 Survivor 分为From和To 每次复制完互换
标记-整理法
解决复制算法对象存活率高时的问题,先标记-然后让存活的向一端移动,以解新内存碎片的问题
分代收集算法
不同的代用不同的方法,针对性的回收
HotSpot实现
- 可达性分析:
- 因为分析准确所以要产生停顿,为了减少停顿,使用准确式GC ,就是虚拟机知道那些地主存着对象引用,使用OopMap数据结构来达到这个目的,这样GC直接扫描就可以了。
- 为了不产生大量的OopMap,只是在特殊的位置(安全点)记录这些信息,程序到了安全点才会停顿,考虑如果安全点少GC等的时间长,如果多大频繁。
- 在安全点时让所有的线程都到这个点,有两种办法一个是抢断式中断,就是所有的都停下来把那些不在安全点的继续运行到安全点,几乎没有用。另一个是主动式中断,就是打标记当线程到这个标记就自己产生中断(身陷)
- 安全区域
- 安全点不能解决程序没有获取CPU时无法产生中断的问题,以所以产生安全区域,就是此区域任何地方都是安全点
执行到安全区域时,标记进来了,然后发起GC,当要离开时如果没有完成根节点的枚举,等待,收到完成的信号后才可以离开
垃圾收集器
- Serial收集器
- 收集时必需暂停其它的所有线程
- ParNew 收集器
- 就是Serial收集器的多线程版本 控制参数与Serial一样,同样是目前能与CMS老年收集器一起使用的年轻代收集器
- 可以通过-XX:ParallelGCThreads来限制垃圾收集器的线程数
- Parallel Scavenge 收集器
- 并行多线程收集器 它的目标是达到一个可控的吞吐量=运行用户代码的时间/(用户代码时间+垃圾回收的时间)适用后始运逄面不需要太多交互的任务
- -XX:MaxGCPauseMills 垃圾停顿时间 大于0 的毫秒数时间短是以牺牲吞吐量和新生代的空间来换的
- -XX:GCTimeRatio 设置吞吐量大小(0-100)
- -XX:+UseAdaptiveSizePolicy 这是一个是否需要手动设置参数的开关,GC会自适应调整策略,但是要设置一个优化的目标就是上面两个参数
- Serial Old 收集器
- 单线程老年代收集器,使用标记-整理,当CMS收集器失败时使用
- Parallel Old 收集器
- 对应Parallel Scavenge收集器,因为Parallel Scavenge无法与CMS收集器一起工作,让吞吐量优化的收集器可以洛地使用
- CMS 收集器
- 是一种以获取最短停顿时间为目标的收集器 一般的b/s系统 上使用,以和用户线程一起工作
- 4个步骤
初始标记 :要停顿
并发标记
重新标记:要停顿
并发清除 - 缺点:对Cpu非常敏感,会占用用户资源
无法处理浮动垃圾 ,如果失败会产生Full GC ,如果运行内存不足会产生失败并用血腥和的Serial Old 进行回收
产生在碎片,如果空间不够时并提前触发Full GC 提供一个-XX:+UseCMSCompactAtFullCollection默认开,就是进行Full GC时整理内存碎片
-XX:CMSFullGCsBeforeCompaction 执行多少次不压缩整理后,执行一次内存整理,默认是0,每次都执行
- G1 收集器
- 前沿成果,生产环境中没有大量使用
并行与并发 分代收集 空间整合 可预测停顿(看书了解)
GC 日志
- GC , Full GC 停顿类型,如果手动调用System.gc()会产生Full Gc(System)
- [ 前数的数字是代表GC 发生的时间参考是虚拟机启动以来的秒数
- DefNew 新生代发生 ParNew 使用ParNew收集的新生代,PSYoungGen 是Parallel Scavenge对应的新生代
- Tenured 老年代 Perm 永久代 名称也与收集器对应
- a->b(c) d secs a是已使用的,b是已使用的 c是总容量 d 表示该区域GC使用的时间,单位是秒有的会给时更详细的时间
墙钟时间 包含阻塞时间
分配策略
优化分配在Eden上
- -XX:+PrintGCDetails 告诉虚拟机发生垃圾回收果打印回收日志
- Minor GC 新生代GC 频繁 速度快
Major GC/Full GC 老年代 比新生代慢10倍以上
大对象直接进入老年代
- 就是很长的字符串或者数组
- -XX:PretenureSizeThreshold 大于这个参数对象直接在老年代分配,只对Serial 和ParNew收集器有效
- -XX:MaxTenuringThreshold 晋升到老年代年龄设置
- 如果Survivor相同年龄的对象大小占总空间的一半,也直接进行老年代
如果有担保 那么如果空间不足会进行Full GC腾出更多的空间
** 参考深入理解Java虚拟机第三章 **
JVM 垃圾收集与内存分配的更多相关文章
- JVM(十一):内存分配
JVM(十一):内存分配 在前面的章节中,我们花了大量的篇幅去介绍 JVM 内的内存布局.对象在内存中的状态.垃圾回收的算法和具体实现等.今天让我们探讨一下对象是如何分配内存的. 堆内存划分 前面说过 ...
- 深入理解JVM(5)——垃圾收集和内存分配策略
1.垃圾收集对象 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 哪 ...
- Java Web 深入分析(12) JVM(2) 垃圾收集与内存分配
前言 java的内存分配和垃圾回收往往是影响系统性能和并发能力的主要因素,虚拟机提供许多的参数就是为了根据不同环境和请教下进行调优,没有最好的调优也没有固定的调优.需要我们深入的去了解jvm的各个垃圾 ...
- jvm(2):垃圾收集和内存分配
typora-root-url: ./ 垃圾收集 垃圾收集器关注的是线程共享的这部分内存. jvisualvm用来监控JVM的运行情况,可以用它来查看和浏览Heap Dump.Thread Dump. ...
- JVM读书笔记之垃圾收集与内存分配
1 概述 说起垃圾收集( Garbage Collection , GC ) ,大部分人都把这项技术当做 Java 语言的伴生产物.事实上, GC 的历史远远比 Java 久远,1960 年诞生于 M ...
- JVM学习之内存分配一
转自:http://blog.csdn.net/mazhimazh/article/details/16879055,多谢博主分享 我们知道计算机的基本构成是:运算器.控制器.存储器.输入和输出设备, ...
- JVM探秘:内存分配与回收策略
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 内存分配一般关注的是对象在堆上分配的情况,对象主要分配在新生代的Eden区中,如果启用 ...
- 深入理解Java虚拟机二:垃圾收集与内存分配
垃圾收集:垃圾收集要完成三件事,包括哪些内存需要回收,什么时候回收及如何回收. 1.需要回收的内存判定:没有引用指向原先分配给某个对象的内存时,则该内存是需要回收的垃圾 Java垃圾收集器在对内存进行 ...
- JVM之---Java内存分配参数(第四篇)
1.内存分配参数---大纲 Ø如何设置堆内存 Ø如何设置栈内存 Ø如何设置方法区 Ø如何设置对的分配比率 Ø设置参数打印堆栈: ØJava程序的两种模式:Server&Client 2.设置堆 ...
随机推荐
- seo搜索引擎的优化方法
现在互联网的入口,一般都是被搜索引擎霸占.所以我们要想让别人搜索时,优先看到我们的网站.有两种方法: 1.竞价排名.这是需要钱的,给的钱越多,排名越靠前.参考某度.. 2.不想花钱,就使用seo搜索引 ...
- List之ConcurrentModificationException异常
一.前言 Java开发工作中,集合类ArrayList应该是使用非常频繁了.在使用过程中,可能会遇到迭代删除的需求场景,此时如果代码书写不当,就会抛出 java.util.ConcurrentModi ...
- selenium基于java 一 软件安装
学习网站 http://www.testclass.net/selenium_java/ 一·安装java环境及eclipse,网上教程较多不讲 二·下载火狐浏览器(旧版) 下载地址:链接: http ...
- Dubbo学习系列之八(分布式事务之MQ方案)
自从小王玩起了微服务,发现微服务果然很强大,好处真是太多,心中暗喜,然而,却也遇到了分布式中最棘手的问题:分布式事务.小王遍访各路神仙,也无个完美开源解决方案,当然,也有些实际可行的手法,虽不算完美, ...
- eShopOnContainers学习系列(三):RabbitMQ消息总线实践
今天研究了下eShopOnContainers里的RabbitMQ的使用,在项目里是以封装成消息总线的方式使用的,但是仍然是以其发布.订阅两个方法作为基础封装的,我们今天就来实际使用一下. 为了简单起 ...
- 一道题考你对__autoreleasing和__block的理解
考虑下面的代码,有哪些问题,如何把他改成正确的形式? @interface TestObj : NSObject @end @implementation TestObj - (void)method ...
- 使用golang插入mysql性能提升经验
前言 golang可以轻易制造高并发,在某些场景很合适,比如爬虫的时候可以爬的更加高效.但是对应某些场景,如文件读写,数据库访问等IO为瓶颈的场合,就没有什么优势了. 前提基础 1.golang数据库 ...
- Python读取excel 数据
1.安装xlrd 2.官网 通过官网来查看如何使用python读取Excel,python excel官网: http://www.python-excel.org/ 实例: (1)Excel内容 把 ...
- 浅析MVC Pattern
一.前言 最近做CAD插件相关的工作,用到了一些模式,解决对应场景的问题. 比如插件的运行实例上使用Singleton.实例内部使用了MVC(Strategy and Observer ). 针对CA ...
- flask 源码解析:上下文(一)
文章出处 https://www.cnblogs.com/jackchengcc/archive/2018/11/29/10025949.html 一:什么是上下文 每一段程序都有很多外部变量.只有 ...