JVM垃圾收集器与内存分配策略学习总结

方法区:

1.线程共享
2.储存类信息,常量,静态变量,编译器编译后的代码
3.非堆(别名)用于区分Java堆
4.不需要连续的内存
5.可以固定或可扩张
6.选择不实现垃圾回收//这个区域很少进行垃圾回收
7.针对常量池回收
8.对类型的卸载
9.无法满足内存分配需求抛出OutOfMemoryError4

虚拟机栈(VM Stack):

1.线程私有
2.生命周期和线程相同
3.描述Java方法执行的内存模型(每个方法执行会创建一个栈帧)
4.栈帧
5.线程请求深度大于虚拟机允许深度抛出StackOverFlowError
6.扩展无法申请到足够内存抛出OutOfMemoryError

本地方法栈(Native Method Stack):

1.为本地方法服务
2.区别于虚拟机栈: 为虚拟机执行Java方法服务
3.抛出StackOverFlowError, OutOfMemoryError

Heap:

1.Java虚拟机所管理最大一片内存区域
2.线程共享
3.虚拟机启动时创建
4.存放对象实例,数组
5.垃圾回收管理GC主要区: 收集器采用分代收集算法,
6.可划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer TLAB)
7.物理逻辑不连续,逻辑顺序连续即可
8.可通过-Xmx和-Xms控制大小
9.堆无法扩展时抛出OutOfMemoryError

程序计数器:

1.较小内存空间
2.当前线程行号指示器
3.线程私有内存
4.唯一个没有OutOfMemoryError区域

直接内存:

1.NIO中使用Channel,Buffer的IO方法,使用Native函数库直接分配的堆外内存
2.会抛出OutOfMemoryError

对象创建:

1.类加载检查机制
2.为新生对象分配内存
3.把一块确定大小的内存从堆中划分出来:
4.将分配的空间初始化为0(不包含对象头)
5.对对象进行必要设置
6.属于哪个类的实例
7.如何找到类的元数据信息
8.对象的哈希值
9.对象的GC分代年龄
10.这些数据存放在对象头(Object Header)中
11.对象得到创建,但是所有字段为0,在执行new之后立即执行方法

对象的内存布局:

1.对象(Object Header):存储对象自身运行时数据(Mark Word):哈希码,GC分代年龄,锁状态标识,线程持有锁,偏向线程ID,偏向时间戳
2.类型指针:对象指向它的类元数据的指针—虚拟机通过该指针确定该对象属于哪个类; 不是所有的对象实例都保留有类型指针; 如果对象是数组,还必须有一块用于记录数组长度的数据
3.实例数据(Instance Data)真正存储的数据: 储存顺序受到虚拟机分配策略参数(Fields Allocation Style)和字段在Java源代码中定义顺序的影响
4.对齐填充(Padding):仅起占位作用

对象访问定位

Java通过栈上引用(reference)数据来操作堆上具体对象
句柄访问:
1.堆中划分一块内存作为句柄池
2.reference中存储对象的句柄地址
3.句柄中包含对象实例数据与类型数据各自的具体地址信息
优点:reference中存储稳定的句柄地址,在对象移动时只会改变句柄中的实例数据指针

GC算法

早期GC算法:
引用计数法:对象获得一个引用计数器,有地方引用,则记数器+一次,当计数器为0表示对象不被引用,垃圾回收器进行回收过程; 但是无法解决对象之间循环引用
例: A obj1=new A();B obj2=new A();
obj1.a=obj2;obj2.a=obj1;obj1=null;obj2=null;
java采用可达性分析算法:
当对象到GC Roots没有任何引用连接的时候,此对象是死缓状态,被进行标记,若该对象没有覆盖finalize()/该方法已被调用过,则此对象在第二次被标记的时候移出回收集合,发生回收
引用------
强引用:强引用存在就不会被GC
软引用:有用单非必须的对象,程序发生OOM之间进行二次回收,如果二次回收没有足够的内存,抛出OOM
弱引用:只能活到GC之前,GC时候无论内存够不够,都会被回收
虚引用:用于引用关联对象被GC时会收到一个系统通知

回收方法区:
1.废弃常量:常量池中一个常量没有引用指向,GC时将会被内存回收
2.无用类:该类所有实例被回收,加载该类的ClassLoader被回收,Class对象没有地方引用,不能通过反射访问该类

GC算法:
1.标记清除算法:首先标记对象,GC时进行清除; 缺点:产生大量不连续的内存空间碎片
2.复制算法: 将内存划分为大小相等的两块内容,每次只使用其中的一块,每次GC时将该内存上的对象移动到另一块内存上,对使用过的空间进行清除
改进措施–新生代更新速度快,内存划分比例不是1:1,按一大一小处理
3.标记整理算法:所有存活的对象往内存的一段移动,清理边界的对象
4.(最常用)分代收集算法:根据对象生存周期不同将内存划分为新生代(大量对象死去,存活率低,复制算法),老生代(对象存活率高,标记清除),根据每块区域的不同使用合适的算法

HotSpot(热区)

可达性分析:
1.枚举根节点(线程必须停顿,即使CMS收集器),逐一枚举GC Roots节点引用链上节点必然不可能,大多数采用OopMap根据对象地址偏移量计算其位置或者JIT编译过程中,将特定位置记录放入栈/寄存器中
2.GC停顿:分析期间为保证分析的准确性,引用不能变化,GC时必须暂停所有Java执行线程
3.OopMap系统停顿时,不需要检查所有执行上下文及全文引用位置,而使用OoMap; 类加载完成时,HotSpot会记录偏移量上的类型供GC扫描
4.SafePoint(安全点,在特定位置停住执行GC):程序并非在所有位置都停顿下来进行GC, 只有达到SafePoint时才停顿; SafePoint不能太少导致GC等待时间过长, SafePoint不能太多导致GC花费更多内存; 选取标准:是否让程序长时间执行的特征; 例如:方法跳转,调用,异常跳转导致产生SafePoint
5.抢断式中断:首先所有的线程中断,若线程中断的地方不再SafePoint上恢复,让它跑到SafePoint上; 没有虚拟机采用此做法
6.主动式中断:GC是需要中断线程,不直接对线程操作,而是设置一个标志,各个线程主动轮询这个标志,发现标志为真,则自己中断挂起//单个线程在标志上不断轮询,为真,挂起
7.SafeRegion(SafePoint的扩展):一段代码片段中,引用关系不会发生变化,在这个区域中任意地方开始GC都是安全的//比如在线程sleep,blocked的状态下,程序无法响应JVM中断请求

垃圾回收器具体实现:

并行:多个垃圾回收器线程同时运行,但用户线程暂停
并发:垃圾回收器和用户线程同时运行,但在不同CPU上处理

  1. Serial收集器(标记整理算法):最初的收集器; 新生代收集器; 单线程收集器; Client模式下首选;//简单高效没有线程交互开销

  2. ParNew收集器: Serial的多线程版; Server模式下首选,和CMS搭配

3.Parallel Scavenge收集器(复制算法): 新生代收集器; 并行多线程收集器;
用于达到可控的吞吐量, 而不是关注用户缩短线程的暂停时间;意义在于高效率使用CPU,适合于后台运算,不需要太多的交互任务
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间); 精准控制吞吐量参数;
控制最大垃圾收集停顿时间,设置最小时间并不能使系统垃圾收集变快(设置时间:-XX:MaxGCPauseMillis;设置吞吐量:-XX:GCTimeRatio);
GC自动适应调整策略:根据当前系统运行情况收集性能监控信息,动态调整新生代大小,Eden与Survivor区比例大小,老年代对象年龄等参数,无需手工设置,提供最合适的停顿时间或者最大的吞吐量(-XX:+UseAdaptiveSizePolicy)
注:不能和CMS搭配

Serial Old收集器
1.Serial老年代版本
2.单线程收集器
3.使用标记整理算法
4.主要是Client端虚拟机使用
5.如果Server模式下,主要用于—JDK1.5以前配合Parallel Scavenge使用; 作为CMS的后备预案,在并发收集发生Concurrent Mode Failure时使用

Parallel Old收集器
1.Parallel Scavenge收集器的老年代版本
2.多线程收集器
3.使用标记整理算法

CMS(Concurrent Mark Sweep//并发标记清理)大多数集中在B/S架构
1.获取最短回收停顿时间为目标
2.使用标记清理算法
3.运作过程如下—
–初始标记(CMS inital mark):标记GC Roots能直接关联到的对象,速度快
–并发标记(CMS Concurrent Mark):进行GC Roots Tracing的过程
–重新标记(CMS remark):修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,比如初始化标记稍长,但远比并发标记时间短
–并发清除(CMS Concurrent Sweep)
4.CMS收集器的内存回收过程是与用户并发执行的
5.CMS明显的缺点:
–CPU大于4个,CMS回收垃圾线程随CPU数量的增加而减少; 当CPU数量少于4个, CMS对用户程序的影响变得很大
–增量式并发收集器(Incremental Concurrent Mark Sweep/i-CMS)效果一般,不推荐使用
–无法处理浮动垃圾,Concurrent Mode Failure会导致另一次Full GC生产而只能将这部分回收失败的垃圾留在下次GC再清理,因此CMS必须预留一部分空间提供给并发收集时的程序使用
6.JDK1.5默认设置老年代使用86%后激活CMS收集器,若老年代增长不是太快,可以提高参数(-XX:CMSInitiatingOccupancyFraction)触发百分比; JDK1.6,CMS启动阀值已经提高到92%
7.如果运行期间预留的内存不够CMS,会出现Concurrent Mode Failure, 此时启动后备预案:临时启动Serial Old收集器重新进行老年代垃圾收集,但会导致停顿时间很长;因此提高触发百分比参数容易导致性能降低
8.标记算法容易产生很多内存碎片
9.CMS提供一个-XX:UseCMSCompactAtFullCollection开关参数,默认开启,用于CMS收集器顶不住Full GC时,开启内存碎片化整理过程,此过程无法并发,停顿时间较长
10.JVM提供-XX:CMSFullGCsBeforeCompaction,用于设置执行多少次不压缩Full GC后进行一次压缩的Full GC(默认为0,表示每次进入Full GC时进行碎片化处理)

G1收集器(标记整理算法):
1.面向服务端应用
2.并行,并发
3.分代收集:将Java堆划分为多个大小相等独立区域(Region),新生代和老生代依旧存在,属于Region的集合
4.空间整理
5.可预测的停顿:
–使用Remembered Set来避免在整个Java堆中进行全区域的垃圾收集
–G1跟踪收集各个垃圾堆积的价值大小(回收所获得的空间及回收所需的时间),后台维护一个优先级列表
–每次根据允许的收集时间,优先回收价值最大的Region(Carbage-First)
6.G1收集器运作大致可划分为一下步骤:
–初始化标记(Initial Marking)
–并发标记(Concurrent Marking)
–最终标记(Final Marking)
–筛选标记(Live Data Counting and Evacuation)

理解GC日志:

例:33.125:[GC [DefNew: 3324K->152K(3712K),0.0025925 secs] 3324K->152K(11904K) 0.0031680 secs]
100.667:[Full GC [Tenured: 0K->210K(10240K),0.0149142 secs]4603K->210K(19456K),[Perm : 2999K->2999K(21248K)],0.0150007 secs][Times:user=0.01 sys=0.00,real=0.02 secs]
1.33.125:/100.667:表示GC发生时间
2."[GC,[Full GC":此次垃圾收集的停顿类型,不能用于区分新生代/老生代GC;Full表示发生停顿
3."[DefNew ,[Tenured ,[Perm":表示GC发生的区域,DefNew(收集器的新生代), ParNew(收集器老生代)
4.“3324K->152K(3712K)”:GC前内存使用量->GC后内存使用量(给内存区域总容量)
5."3324K->152K(11904K):GC前堆已使用量->GC后堆使用量(堆总容量)
6.“0.0031680secs”:内存区域GC所占用的时间
7.[Times:user=0.01,sys=0.00,real=0.02secs]:指用户,内核,操作开始到结束所花的时间

内存回收与分配策略

对象内存分配:
1.堆:大多数分配在堆上的Eden新生代区,TLAB//如果启动本地线程分配缓冲,优先在TLAB上分配,Tenured//直接分配到老年代中
2.栈:JIT编译
注:大对象直接进入老年代, 长期存活的对象进入老年代
动态对象年龄判断:
1.当Survivor中的相同年龄的所有对象的大小总和大于Survivor的一半时,年龄大或者等于该年龄的对象可以直接进入老年代,不用等到MaxTenuredThresold设置的值

空间分配担保:

1.在Minor GC之前,JVM会检查老年代的连续内存空间够不够新生代所有对象的内存空间, 够–Minor GC是安全的, 不够–JVM会查看HandlePromotionFailure设置值是否允许担保失败:大于(尝试进行Minor GC,尽管Minor GC是有风险的),小于(HandlePromotionFailure设置不允许冒险,会进行一次Full GC),允许(继续检查老年代的最大可用连续空间是否大于历次晋升到老年代对象的平均水平)
"冒险"的概念:
1.大量的对象在Minor GC后仍然存活,需要老年代进行分配担保
2.把Survivor无法容纳的对象直接进入老年代
3.进行这样的担保,首先保证老年代空间足够容纳这些对象
4.对象多少能够存活下来再实际完成内存回收之前无法确定,所以按照以前晋升老年代对象容量的品均值作为参考
5.不够,再确定是否需要进行Full GC来腾出更多的空间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汇编比较两个数大小_计算机是怎样跑起来的 -- 体验一次汇编过程

标志内存或I/O中存储单元的数字叫做“地址”。CPU中的标志寄存器有什么作用?用于在运算指令执行后,存储运算结果的某些状态。从程序员的角度看硬件CPU:种类,时钟信号的频率。可以使用哪种机器语言取决于CPU的种类。内存信息&#…

Nginx 作为 WebSockets 代理

WebSocket 协议给我们提供了一个创建可以支持客户端和服务端进行双向实时通信的web应用程序的方法。相比之前使用的方法,WebSocket(作为HTML5的一部分)可以使我们更容易开的发出这种类型的应用程序。绝大多数的现代浏览器都支持WebSocket&…

设计模式小结

开始的毛病:变量命名不规范,if-else判断有的代码做无用功,代码健壮性太差,没有做try-cath异常处理 工厂模式(创建型模式): 创建对象接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建延伸到子类进行 主要解决接口选择问题,明确计划不同条件下执行创建不同实例 通过子…

android区块链 钱包_区块链钱包Cashbox 开发工程师聊一聊开源

今天与大家聊一聊软件开源。事情的起因是一次闲谈的时候,市场部的同事表示:不做软件开发的人不能够理解为什么要把软件源代码公开出去。当时的我很惊讶,因为就像他们不理解为什么要开源一样,我也不理解他们为什么不理解为什么要开…

dom4j创建、解析xml文件(增删改查)

先对xml文件进行解析,xml文件如下图所示 <?xml version"1.0" encoding"UTF-8"?><?eclipse version"3.4"?> <student1> <studentID>001</studentID> <name>sanny</name> <major>…

Java的Class类文件结构及基本字节码指令

Class类文件的结构 概念:Class文件是一组以8位字节为基础单位的二进制流 按顺序整齐排列 没有任何分隔符,内容全部是运行时的必要数据,没有空隙存在 排序方式:高位在前 Big-Endian:最高字节在地址最低位,最低字节在地址最高位 Little-Endian:相反 储存方式:类似于C语言结构体…

Android 7.1 32位apk导致的系统库找不到问题

出现问题 因为我们安卓7.1系统的应用都是64位的APK&#xff0c;我们自己开发的应用是32位的APK&#xff0c;这样在启动的时候&#xff0c;就大概率的出现库找不到的问题。 错误的日志如下&#xff1a; Line 440: 03-12 10:48:39.620 634 634 W PackageManager: Instruct…

python基础知识下载_Python基础知识(一)

一、安装pythonwindow系统下先下载的 python 安装包&#xff0c;直接安装即可。为确认是否安装正确&#xff0c;可用系统记事本创建一个hello.py的程序其中包含如下内容&#xff1a;1 #!/usr/bin/env python32 print("Hello", "World!")代码说明&#xff1…

单词的理解 —— 词义的变化(翻译)

mimic&#xff1a;模仿&#xff0c;摹拟&#xff08;而不是最小化&#xff09;minder&#xff1a;n. 看守者&#xff1b;照顾者 保镖等近似含义&#xff1b;outstanding&#xff0c;outstanding work&#xff1a; 未完成的工作&#xff0c;backlog&#xff1a;n. [管理] 积压的…

JVM类加载机制_字节码执行引擎_Java内存模型

类加载机制: 类加载生命期:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using),卸载(Unloading)初始化:1.遇到new,getstatic,putstatic,invokestatic指令,类没有进行初始化,先触发初始化2.java反射机制3.初始化一个类,…

最新车载导航端口检测工具_高德地图这个功能 把微信都没做好的车载社交解决了?...

在汽车网联化和智能化带给人们的诸多想象里&#xff0c;车内社交似乎是最虚无缥缈的那个。在移动互联网领域&#xff0c;微信通过满足人们社交需求这个基本点&#xff0c;构建起庞大的用户群体&#xff0c;展示出巨大的市场前景。但在驾车场景下&#xff0c;车载社交该怎么玩&a…

王译潇20162314 第九周作业总结

学号 20162314 2016-2017-2 《Java程序设计》第九周学习总结 教材学习内容总结 数据库是为其他程序提供数据的应用软件 关系数据库通过唯一的标识符在不同表的记录间建立了关系 JDBC API用来建立到数据库的连接 CREATE TABLE SQL 语句用来创建新的数据库表 ALTER TABLE SQL 语句…

sketchup边线设置_春天花花天桥,SketchUp草图大师快速建模!

最近小吧在网上看到一座设计很特别的天桥&#xff0c;形状很像一朵花&#xff0c;名字也十分写实——春花天桥。喏&#xff0c;就是下面这个家伙&#xff01;图片来自网络春花天桥是2011年深圳举办大运会前夕投资建设的形象提升工程之一&#xff0c;在建设初期就被定位为地标性…

自言自语

随笔, 自我审视, 需要反思 最近这段时间, 各种艰难困苦早已将最初的激情冲刷地只剩下骨头了, 每天拖着疲惫的身子, 总是做着没有意义的事; 迷失了自我, 总把时间浪费, 而在做浪费时间的事却没有思考做这件事是否是有意义的, 是否是有价值的, 是否是在浪费时间; 没有思考, 就像行…

忧愁无处发

顶着好多方面的压力回家了....过得不好。。。。转载于:https://www.cnblogs.com/ysw6/p/6789910.html

python求直角三角形第三边公式_直角三角形已知两边求第三边公式

展开全部解&#xff1a;分两种情况讨论1、需要求的第三边为斜边时&#xff0c;第e69da5e887aa3231313335323631343130323136353331333433643030三边长度√a^2b^2 (ab分别为两直角边的长度)2、需要求的第三边为直角边时,第三边长度√c^2-a^2 (其中c为斜边,a为已知直角边)扩展资料…

android 7.1 apk的systemuid和系统应用Setting相同导致开机找不到库的问题

1、前言Android apk加载机制这就是我最近在解决的一个问题&#xff0c;32位的apk可以用32位的库&#xff0c;那64位的apk可以用64位的库&#xff0c;如果我想64位的apk同时使用32和64位的库呢&#xff1f;android加载so文件的机制apk在安装的过程中&#xff0c;系统就会对apk进…

Struts2_1_基础案例_配置文件详解_动作类

Struts2简要概述 三层架构中的表现层框架相对于常规的MVC模式, 其核心为Filter控制器内部的Filter实例是在客户端每发送一次就实例化一次, 相比于Servlet具有线程安全性内部控制器默认拦截以.action或无后缀名的url Struts2案例步骤 配置web.xml, 由于Struts2核心为Fiter, 所…

BZOJ 3362 Navigation Nightmare 带权并查集

题目大意&#xff1a;给定一些点之间的位置关系&#xff0c;求两个点之间的曼哈顿距离 此题土豪题。只是POJ也有一道相同的题&#xff0c;能够刷一下 别被题目坑到了&#xff0c;这题不强制在线。把询问离线处理就可以 然后就是带权并查集的问题了。。。将权值设为方向向量&…

怎样的人适合当码农?

1高中的时候&#xff0c;我一个友仔&#xff0c;他说要创办一个科技协会&#xff0c;然后跟我说电脑里面的代码都是0和1组成的&#xff0c;我现在还记得那天我们在学校开会的时候讨论电脑如何运行&#xff0c;我一脸痴呆的听他给我讲解电子知识&#xff0c;而且他后面自己做了一…