CreateArtTechnology
/ Blog
Login
最新文章
Java
语言相关
库相关
虚拟机相关
CreateArtTechnology
项目搭建
使用的工具
自研的工具
开源工具
ELK
ElasticSearch
Jenkins
Markdown
GraphQL
Arthas
生产工具
Linux
Nginx
VersionControl
Subversion
Git
Redis
Archiva
Maven
Zookeeper
Spring
SpringBoot
MySql
HBase
Cassandra
容器化
Docker
Kubernetes
服务容器化从零开始
未分类笔记
算法相关
概念相关
豆知识
机器学习
机器学习从零开始
《深入理解Java虚拟机》笔记<1-自动内存管理机制>
15
2019-06-23 23:16:09
Java
虚拟机相关
## Java内存区域与内存溢出异常 ### JVM运行时数据区 ![](/img/pic/2019062514475609428_png_817_506_106550) > Java使用的内存大致被划分为5个部分 **程序计数器** 参考计算机组成原理,程序计数器跟线程是绑定的,因此是线程私有的。 **虚拟机栈** 参考计算机组成原理,是运行Java方法时使用的栈,每个静态或非静态方法执行时会创建一个栈帧用于存储方法信息、局部变量(包括基本类型和对象引用,至于引用指向的对象则保存在堆中)等,线程私有。 很明显,如果递归层次过深会导致StackOverflowError。 **本地方法栈** 运行Native方法时使用的栈,线程私有。 **方法区** 也就是Perm Generation,永久代。 用于存放已被加载的类信息、每个对象保存的类型数据、常量(Java7开始已不包括字符串常量池)、静态变量等,JVM加载类后将Class文件中定义的常量保存在这里。 由于存放的信息基本是常量性质的,因此是非线程私有的。 **堆** 保存对象实例,非线程私有。 如果持有对象过多内存不足会导致OutOfMemoryError。 ### 对象的定位 **通过句柄** 部分虚拟机实现中,非常量或静态变量的引用(也就是方法栈帧中保存的局部变量)指向的是句柄池中的指针,而句柄池中的指针指向的是真正的对象实例数据(堆中)或对象类型数据(方法区中)。 这种方式的好处是引用直接指向的句柄池地址是不变的,而在句柄池中的指针由于GC的移动或复制等可能经常变化。 ![](/img/pic/2019062514495692129_png_741_336_130833) > 句柄访问 **通过直接指针** 引用直接指向目标对象的对象实例数据(堆中)或对象类型数据(方法区中),在对象访问非常频繁的情况下减少一次寻址开销。 HotSpot使用到的是直接指针定位。 ![](/img/pic/2019062514510678330_png_762_318_113312) > 直接访问 ## 垃圾收集器与内存分配策略 ### 判断对象无引用 **引用计数法** 直接对该对象被持有引用数量计数,计数为0时则没有引用,可以回收。 - 优点:实现简单,效率高 - 缺点:存在循环引用问题 **可达性分析法** 将一部分特殊对象作为GC Root,以此开始搜索其引用的对象,形成引用链。如果某对象不属于引用链,表明引用不可达,可以回收。 - 优点:解决循环引用问题 - 缺点:统计过程中的引用变化会影响分析结果 GC Root通常包括: - 虚拟机栈或本地方法栈中引用的对象 - 方法区中常量或静态属性引用的对象 ### 执行收集的过程 1. 标记某对象不可达 2. 将覆盖了`finalize()`方法且该方法没有被调用过的不可达对象入队,其他对象直接回收 3. 执行队列中对象的`finalize()`方法,不保证执行完毕 4. 标记队列中仍旧不可达的对象 5. 回收 因此,如果一个对象覆盖了`finalize()`方法,则会入队; 如果在入队后,在`finalize()`方法中将自己挂上GC Root的引用链,那么就不会被回收; 但是`finalize()`方法只会执行一次。 ### 堆的空间划分 一般而言堆划分为新生代(Young Generation,包括Eden Space和Survivor Space)、老年代(Old Generation)、永久代(Perm Generation),通过`jmap -heap {pid}`可以查看堆使用状况。 以下是使用G1垃圾收集器的堆分配与使用情况。 ```shell :/path/to/jdk/bin$ ./jmap -heap 25981 Attaching to process ID 25981, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.72-b04 using thread-local object allocation. Garbage-First (G1) GC with 1 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 536870912 (512.0MB) NewSize = 1363144 (1.2999954223632812MB) MaxNewSize = 17592186044415 MB OldSize = 5452592 (5.1999969482421875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 20971520 (20.0MB) MaxPermSize = 134217728 (128.0MB) G1HeapRegionSize = 1048576 (1.0MB) Heap Usage: G1 Heap: regions = 410 capacity = 429916160 (410.0MB) used = 286785552 (273.50001525878906MB) free = 143130608 (136.49998474121094MB) 66.7073207948266% used G1 Young Generation: Eden Space: regions = 180 capacity = 245366784 (234.0MB) used = 188743680 (180.0MB) free = 56623104 (54.0MB) 76.92307692307692% used Survivor Space: regions = 25 capacity = 26214400 (25.0MB) used = 26214400 (25.0MB) free = 0 (0.0MB) 100.0% used G1 Old Generation: regions = 70 capacity = 158334976 (151.0MB) used = 71827472 (68.50001525878906MB) free = 86507504 (82.49998474121094MB) 45.36424851575435% used Perm Generation: capacity = 44040192 (42.0MB) used = 43632120 (41.61083221435547MB) free = 408072 (0.38916778564453125MB) 99.07341003417969% used ``` ### 垃圾收集算法 **标记清除** 1. 引用分析,对不可达对象打标记 2. 清除被标记的对象 ![](/img/pic/2019062514524598031_png_851_453_162223) 优点:简单,不需要移动对象 缺点:产生内存碎片 **标记复制** 1. 引用分析 2. 将存活对象复制到另一块内存 3. 整块回收原本那块内存 ![](/img/pic/2019062514530790732_png_857_464_211853) 优点:不产生碎片,清除大块连续空间效率比较高 缺点:浪费部分内存 新生代对象基本是使用标记复制的方法。 **标记整理** 1. 引用分析 2. 类似选择排序,将存活对象移动到一起,消除内存碎片 3. 清除其他连续内存 ![](/img/pic/2019062514532839733_png_789_418_70129) 优点:不产生碎片,不浪费内存 缺点:未知 ### 新生代垃圾收集器 **Serial** - 使用标记复制算法 - 单线程 - 无法与用户线程并发,整个收集过程处于Stop The World **ParNew** - 使用标记复制算法 - 多线程 - 无法与用户线程并发,整个收集过程处于Stop The World **Parallel Scavenge** - 使用标记复制算法 - 多线程 - 无法与用户线程并发,整个收集过程处于Stop The World - 可控制吞吐量和最大GC停顿时间 ### 老年代垃圾收集器 **Serial Old** - 使用标记整理算法 - 单线程 - 无法与用户线程并发,整个收集过程处于Stop The World **Parallel Old** - 使用标记整理算法 - 多线程 - 无法与用户线程并发,整个收集过程处于Stop The World - 可控制吞吐量和最大GC停顿时间 **CMS** - 使用标记清除算法/标记整理算法 - 多线程 - 中间部分过程处于Stop The World,其他过程可与用户现场并发 CMS收集清理过程: 1. **初始标记**:找到GC Root直接关联的对象,Stop The World,单线程,工作量小耗时低 2. **并发标记**:搜索初始标记相关的完整引用链,可与用户线程并发完成,单线程,工作量大耗时较高 3. **重新标记**:寻找在并发标记过程中被用户线程修改的引用情况,Stop The World,多线程,工作量稍大但耗时较低 4. **并发清理**:清理被标记的对象,可与用户线程并发完成,单线程,工作量大耗时较高 ![](/img/pic/2019062514550753234_png_935_183_97013) > CMS收集清理过程 ### 新生代与老年代共用 **G1** - 参考前文G1堆分配与使用情况,仍使用分代,但以Region为单位 - 使用标记整理(Region内)+标记复制(Region之间)算法 - 优先回收价值大的Region,即垃圾空间大小与回收所需时间的经验值 G1收集清理过程: 1. **初始标记**:找到GC Root直接关联的对象,Stop The World,单线程,工作量小耗时低 2. **并发标记**:搜索初始标记相关的完整引用链,可与用户线程并发完成,单线程,工作量大耗时较高 3. **最终标记**:寻找在并发标记过程中被用户线程修改的引用情况,Stop The World,多线程,工作量稍大但耗时较低 4. **筛选回收**:清理价值高的Region,Stop The World,多线程,但吞吐量和耗时可控 ![](/img/pic/2019062514560335135_png_951_205_136999) > G1收集清理过程 ### HotSpot的GC过程 **枚举根节点** 从GC Root的对象开始分析所有可达的存活对象,那么首先就需要找出所有GC Root节点。 这一步需要Stop The World。 **到达安全点或安全区域** GC线程对活动线程设置标记,所有其他线程在到达方法调用、循环跳转、异常跳转时进入Safe Point安全点;或是检查到线程处于Sleep等未获取CPU时间的状态时认为其进入了Safe Region。 安全点或安全区域可以认为是GC收集器可以安全进行收集和清理的时机。 **使用垃圾收集器收集和清理垃圾** 使用指定的垃圾收集器收集并清理垃圾,期间可能经过MinorGC或FullGC/MajorGC。 - MinorGC:新生代GC,比较频繁,由于新生代存活率低,回收速度较快 - FullGC/MajorGC:老年代GC,不频繁,一般还会伴随MinorGC,回收速度慢 ### 内存分配与回收策略 **优先在Eden分配** 新对象一般优先在Eden分配,Eden空间不足时触发MinorGC。 MinorGC过程中Eden区及使用中的Survivor区的存活对象被标记复制到另一个空闲Survivor区。 这样一来新生代浪费了一个Survivor区的空间,不过由于新生代存活率低(每次GC约2%存活),默认空间大小Eden : Survivor = 8 : 1,也就是说浪费了新生代10%空间。 **大对象直接进入老年代** 大小超过阈值的对象直接分配在老年代中,避免频繁复制大对象。 老年代空间不足显然需要进行MajorGC。 **长期存活的对象进入老年代** 每次MinorGC会给存活对象年龄自增1,默认年龄达到15后或晋升到老年代。 老年代空间不足显然需要进行MajorGC。 **动态年龄判断** 同年龄对象占用空间达到Survivor区一半时,大于等于这个年龄的对象都会进入老年代。 老年代空间不足显然需要进行MajorGC。 **空间分配担保** Survivor区放不下的对象可以分配在老年代,这也就是老年代为新生代分配担保。因此,需要老年代预留出一部分空间用于应对担保。 Survivor区放不下,意味着此时在进行MinorGC,所以空间担保检查需要在MinorGC开始前进行。 - 老年代最大可用连续空间大于新生代已用总空间,那显然担保无风险,MinorGC可进行 - 老年代最大可用连续空间大于历次晋升到老年代对象的平均大小,说明担保有风险,但MinorGC可进行 - 其他情况,担保有较大风险,需要先进行一次MajorGC
发布文章 101
文章被阅读 1817
最近修改
什么是“丝滑”的曲线
2021-12-08 15:19:20
高效空间数据索引R树及其批量加载方法STR简介
2021-09-29 20:33:37
关于分库分表的一些事儿
2021-06-25 11:51:25
获得诺奖的稳定匹配理论之TTC算法与GS算法
2021-03-14 23:04:48
算法小白的机器学习入门实践,从零到上线
2021-01-13 14:28:27
分站宗旨
一站式资料平台,减少重复检索,减少重复采坑。