0
点赞
收藏
分享

微信扫一扫

jvm基础大回顾

运行时数据区域

线程共享:堆和方法区
线程独享:虚拟机栈,本地方法栈,程序计数器

对象在内存中的分布

对象结构包括对象头和对象体
对象在内存中定位包括直接指针和句柄池两种方法

如何分配对象内存

指针碰撞:内存规整,指针移动对象大小的距离即可完成分配;
空闲列表:内存不规整,需要维护一个空闲列表,记录空闲的位置以及位置大小,找到合适的空间进行分配;
tlab:线程本地分配缓冲,并发情况下每个线程在堆中预先分配一小块内存,哪个线程要分配内存就在其本地缓冲区分配,直到分配新的缓存区才需要同步锁定;

对象回收
先判生死
引用计数法:对象记录其他对象对他的引用情况,引用失效再更新,可能产生循环引用,无法被回收
可达性分析:GCroot根节点枚举,采用三色标记法,没有被标记到的对象被回收

回收算法
标记清除:标记后清除,会产生内存碎片但是快,不会STW
标记复制:标记后复制存活对象到未使用空间,一次性清理原空间,复制对象要STW,并且要浪费内存空间
标记整理:标记后将存活对象移动到一处,清理存活对象所在区域指针后面的所有空间,移动对象同样要STW
分代收集:将内存区域分为新生代和老年代,按照不同的策略收集,新生代一般采用标记复制算法,又分为eden和suivivor(两个),默认比例8:1:1,每次只启用eden和一块survivor,将eden区和原survivor存活对象复制到空闲survivor,并一次性清理;
老年代一般采用标记整理算法(老年代的存活对象多)

新生代收集器(均采用标记复制)
serial:单线程
ParNew:多线程收集
Parallel Scavenge收集器:同样多线程,可控吞吐量

老年代收集器
Serial Old收集器:单线程
Parallel Old收集器:Parallel Scavenge收集器的老年代版本

CMS:并发低停顿,采用标记清除算法(碎片化)
初始标记 根节点能直接关联到的对象
并发标记 根节点枚举
最终标记 使用增量更新来解决并发标记的问题,记录下并发标记过程中有黑色对白色的引用,黑色变为灰色重新进行遍历
并发清除 回收
耗时最长的并发标记和并发清除都

G1:基于region的,能独立管理堆,采用不同方式管理region,从整体看是标记整理算法,局部看是标记复制算法,都不会产生内存碎片,低停顿高吞吐量,可建立停顿时间模型(维护一个优先列表)
初始标记
并发标记
重新标记 采用原始快照的方式解决并发标记的问题,记录断开了白色对象的灰色对象,并重新扫描
筛选回收

对象的内存分配策略
对象优先在eden区分配
大对象直接进入大年代(复制成本高)
动态年龄判定:新生代的对象每熬过一次收集都会在对象头记录,到达15后进入老年代,或者同一年龄的对象超过survivor的一半,大于等于此年龄的升入老年代
空间分配担保机制:如果允许冒险,则根据历史经验尝试只收集新生代(老年代可能能容纳晋升对象),如果失败还是会触发full gc

GC流程
新生代GC在空间分配担保机制下进行,一旦失败就会触发fullGC

类加载

加载 验证 准备 解析 初始化
根据类名获得二进制流,并将类信息加载进方法区,创建类对象
验证文件格式和规范
将类变量初始化为0
将符号引用解析为直接引用
执行类的init方法,将类变量按照预定规则初始化

双亲委派机制

启动类加载器
拓展类加载器
应用程序类加载器

执行类加载时先委派给父类加载,直到父类不能加载才让子类加载,通过类加载器可以保证只加载一个Object类,具有唯一性

三次打破
1.自己实现类加载器并继承classloader,重写loadclass方法
2.SPI(服务提供者接口),如JDBC,使用线程上下文加载器,父类委托子类去加载
3.OSGI实现模块化热部署,网状的,有平级依赖关系

举报

相关推荐

【JVM】JVM基础

回顾基础--HTML篇

java基础学习回顾

java基础回顾一

Python基础回顾(2)

JVM基础

面向对象基础小回顾

0 条评论