[Reading] Asking while Reading
Asking while Reading
——读Java垃圾收集器与内存分配策略
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。
为什么要了解垃圾回收?
当需要排查各种内存溢出、内存泄漏问题的时候,当垃圾回收成为了系统达到更高并行量的瓶颈的时候,我们就需要根据情况(往往是根据硬件和程序
以及它们在各种垃圾回收算法下运行的情况)选择恰当的垃圾回收方式,作出必要的监控和调节。
哪些内存需要回收?
换一句话来说:哪些内存可以回收,哪些内存又值得回收;可以回收明确我们的执行范围,而回收价值明确我们的主要目标,当然这不是一定的,
对每个项目都可能有不同的着眼点,这也是我们要理解垃圾回收方法与过程的原因。
Java堆和方法区与栈不同,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运
行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾回收器关注的是这部分内存。
方法区也需要回收吗?
方法区可以不回收,因为Java虚拟机规范中说过不要求虚拟机在方法区中实现垃圾收集,更重要的原因是其性价比一般较低,原因如下:
我们知道对方法区的收集集中在对常量、无用的类的收集。
1) 效率:常规一次垃圾收集可以回收70%~95%的空间,而根据我以往的经验,一般情况下,常量的占用空间之小和方法的调用区域之广泛让放置永
生代的方法区的效率远低于此。
2) 条件:虽然判定一个常量是否废弃比较简单,但Java的反射思想让类的废弃判定格外苛刻:
a) 该类所有的实例都被回收
b) 加载该类的ClassLoader已经被回收
c) 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
那回收方法区还有意义吗?
并非存在即有意义,当然它也有自己的运用场合:尤其在WEB或用到控制反转思维的应用中大量使用反射、动态生成JSP这类频繁自定义ClassLoader的
场景都需要虚拟机具备类卸载的功能,以保证永生代不会溢出。
如何判断是否可以回收?
我们已然明确了哪些内存可以回收,但是在一个时间点具体地如何去回收呢?虽然在python中采用了引用计数算法,但是我得很遗憾地告诉你,这
样做并不可靠,并且更关键地是Java并没有采用这一算法。
在堆里存放着Java世界里几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还存活着。
引用计数算法
方法:给对象添加一个引用计数器,每当有一个地方引用它,计数值加一;当引用失效时,计数值减一。因此,当对象的计数值为0时就可以被清除
掉了。
缺陷:(致命)如果两个对象互相引用,然后我们又丢掉了对这两个对象的引用,那么引用计数算法就无法通知GC收集器回收它们的空间。
可达性分析算法
根据图论中可达性的思想以一些静态地点(如虚拟机栈、方法区中类静态属性、方法区中常量)引用的对象为起始点,从这些节点开始向下搜索,那
些不可达的对象就是可回收的对象。
如何回收?
实际上,这一部分并不会给出最好的算法,在IT行业也是这样,只有更适合问题的方法,没有适合所有问题的方案。
标记清除算法(最基础)
过程: 标记:标记所有需要回收的对象。(在前面已经讲述)
清除:在标记完成后统一回收所有被标记的对象。
缺点: 1)效率:标记和清除两个过程的效率都不高
2) 空间:操作完成后会产生大量内存碎片
复制算法(解决效率问题)(新生代)
过程: 将内存分为三块,一块较大的Eden空间和两块较小的Survivor空间。当回收时,将Eden和Survivor中存活的对象一次性复制到另一块Survivor空间
里,最后清理掉Eden和Survivor中的数据。
优点: 因为大多数新生代存活时间都比较短,付出少量的内存空间(一般是8:1:1)就可以达到很好的效果(根据IBM一项调查显示,新生代的对象98%
都是“朝生夕死”)。
缺点: 在Survivor区域不够时,就要依赖其他区域(老生代)进行分配担保,实在不行只得进行全内存的垃圾回收。所以这不适用于一些新生代很大、
生存周期又较长的情况。
标记-整理算法(新生代)
过程: 标记过程仍和“标记-清除”算法一样,但之后是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
优点: 1)不需要额外的空间闲置不用。(或称为分配担保)
2) 有效地解决了复制算法中当对象存活周期长的缺点
缺点: 也正如它所要解决的问题,它不能解决老生代成片地存活周期长的问题,因为正如数组的移动,低效随之而来。
分代收集算法
当前虚拟机都采用“分代收集”的思想,说其为思想,因为我想其中并没有什么新的内容,只不过是继承前面的思想,面对不同问题选用不同的手段罢了。
在新生代中,只有少量的对象存活,那就采用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
在老生代中,因为对象存活率高、没有额外空间对它进行担保,那就必须采用“标记-清理”或者“标记-整理”的算法进行回收。
如今编译器中采用的垃圾收集器:
新生代:Serial、ParNew、Parallel Seavenge
老生代:CMS、Parallel Old、Serial Old
以及较为综合的G1收集器都是建立在以上思想的基础之上,其中的区别也往往是是否面向多线程?是否着重考虑单次收集时间(增加次数减少
间断)还是着重考虑CPU占用时间(增加每次间断时间而减少间断次数),这也是与客户体验和服务器处理性能相关的。我们需要做的只是针对特定情况设
定合适的参数而已了。有了以上的基础知识,我相信能在处理垃圾收集问题时候会有一个清晰的方向。
[Reading] Asking while Reading的更多相关文章
- The Power of Reading——英语学习小技巧之七
This method is "The Power of Reading" and it comes from an article by Dr.Stephen Krashen. ...
- Reading C type declarations(引用http://unixwiz.net/techtips/reading-cdecl.html)
Even relatively new C programmers have no trouble reading simple C declarations such as int foo[5]; ...
- Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:9001/api/size/get. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http:/ ...
- Git Learning - By reading ProGit
Today I begin to learn to use Git. I learn from Pro Git. And I recommend it which is an excellent bo ...
- MySQL远程连接丢失问题解决方法Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0
最近远程连接mysql总是提示 Lost connection 很明显这是连接初始化阶段就丢失了连接的错误 其实问题很简单,都是MySQL的配置文件默认没有为远程连接配置好,只需要更改下MySQL的配 ...
- 论文阅读(Weilin Huang——【AAAI2016】Reading Scene Text in Deep Convolutional Sequences)
Weilin Huang--[AAAI2016]Reading Scene Text in Deep Convolutional Sequences 目录 作者和相关链接 方法概括 创新点和贡献 方法 ...
- Flesch Reading Ease -POJ3371模拟
Flesch Reading Ease Time Limit: 1000MS Memory Limit: 65536K Description Flesch Reading Ease, a reada ...
- Mac下遇到 'reading initial communication packet’ 问题
今天在开发过程中,一个单位跑的好好的项目,在家中的Mac下运行时,遇到了下面这个错误: "Lost connection to MySQL server at 'reading init ...
- A log about Reading the memroy of Other Process in C++/WIN API--ReadProcessMemory()
Memory, is a complex module in Programing, especially on Windows. This time, I use cpp with win wind ...
随机推荐
- mysql 锁表查看
information_schema.INNODB_TRX 一般锁表后查询这个表 把相关的事务执行线程kill就可以了,可以分析sql语句执行场景 INNODB_LOCKS PROCES ...
- MyBatis 基础入门
MyBatis 是一个半自动化的持久层的框架,能让开发者专注SQL本身 JDBC 连接数据库的硬编码问题,通过config,mapper配置文件解决 Mybatis开发需要关注的文件 l POJO类( ...
- 如何使用Matlab做数字信号处理的仿真1
例如 第三版数字信号处理P51 -1.14习题时域离散信号的相关性研究x(n)=Asin(ωn)+u(n),其中ω=π/16,u(n)是白噪声,现要求 ⑴.产生均值为0,功率P=0.1的均匀分布白噪声 ...
- jq操作table追加td
示例 代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档
0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...
- Vue学习之路第十六篇:车型列表的添加、删除与检索项目
又到了大家最喜欢的项目练习阶段,学以致用,今天我们要用前几篇的学习内容实现列表的添加与删除. 学前准备: ①:JavaScript中的splice(index,i)方法:从已知数组的index下标开始 ...
- BZOJ 3158 千钧一发 (最大流->二分图带权最大独立集)
题面:BZOJ传送门 和方格取数问题很像啊 但这道题不能像网格那样黑白染色构造二分图,所以考虑拆点建出二分图 我们容易找出数之间的互斥关系,在不能同时选的两个点之间连一条流量为$inf$的边 由于我们 ...
- alsa-lib 交叉编译以及声卡驱动测试 (转)
l 下载alsa-utils, alsa-lib, 版本要一致 http://www.alsa-project.org/main/index.php/Download l 编译alsa-lib . ...
- C#实现简单的串口通信
前言 本着学习研究的态度,用c#语言实现简单的串口通信工具. 一.串口通信原理 串口通信 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节.尽管比 ...
- xml00
<?xml verson="1.0" encoding="ISO-8859-1"?> xml声明<note> <to>jon ...