当前位置:网站首页>JVM内存和垃圾回收-07.堆
JVM内存和垃圾回收-07.堆
2022-08-04 02:38:00 【J___code】
1.核心概述
- 一个JVM只存在一个堆内存
- 堆在JVM启动时就被创建,大小也确定下来了(可以调节)
- 堆可以在物理上不连续,逻辑上视为连续
- 所有线程共享Java堆,但可以划分线程私有的缓冲区(TLAB)
- 所有对象实例和数组都分配在堆上
- 方法结束后堆中的对象不会马上被移除,在GC时才被移除(堆是GC的重点区域)
- 内存细分:
- Java7及之前堆内存逻辑上分为:新生区+养老区+永久区
- Java8及之后堆内存逻辑上分为:新生区+养老区+元空间
2.堆空间大小设置
- -Xms:表示堆区(年轻代+老年代)的起始内存(默认物理电脑内存大小/64)
- -Xmx:表示堆区(年轻代+老年代)的最大内存,堆中内存大小超过该值就抛出OOM(默认物理电脑内存大小/4)
通过将上述两个参数设置为相同的值,目的是在GC清理完堆区后不需要重新分隔计算堆区大小,提供性能
3.年轻代和老年代
在JVM中的对象可以根据存活时间分为两类:
生命周期短的对象,该类对象的创建和消亡非常迅速
生命周期长的对象,该类对象没必要每次GC都去判断是否回收
堆区的划分(一般不包括方法区)可以进一步分为年轻代和老年代(可以通过
-XX:NewRatio
设置二者占比;通过-XX:SurvivorRatio
设置年轻代中三个部分的占比)
- 几乎所有Java对象都是在Eden区被new出来的(一些较大的对象并不是在该区new出来的)
- 大部分的Java对象的销毁都是在新生代进行(即GC频繁发生在新生区,很少在养老区,几乎不在永久区/元空间收集)
为什么要分代?为了优化GC性能。假如不分代,则GC的时候要找到哪些对象没用,则需要对整个堆进行扫描。其实很多对象都是存活周期很短,把这些对象放在一个特定的地方(即分代),GC的时候就可以经常去处理这块区域
4.对象分配过程
内存分配算法和内存回收算法密切相关,所以需要考虑GC执行完内存回收后是否会存在内存碎片
对象分配过程如下:
- new的对象放在Eden区
- Eden区填满后,此时程序还要继续创建对象时,垃圾回收器会在Eden区进行GC(
Minor GC
/Young GC
),将该区中不再被其他对象引用的对象销毁,然后再加载新对象 - 将Eden区中剩余对象移动到
Survivor0
区(绿色代表幸存对象,红色代表被GC的对象,数字1表示年龄计数器为1)
- 如果再次触发垃圾回收,会将此次幸存对象(Eden区的)和在
Survivor0
区且未被GC的对象都放在Survivor1
区,同时年龄计数器也要相应改变(注意此时Survivor0
区变空)。此时的Survivor0
区为from区,Survivor1
区为to区
下次再进行GC就是将当前Eden区幸存对象和在在
Survivor1
区且未被GC的对象都放在Survivor0
区。此时的Survivor1
区为from区,Survivor0
区为to区当在
Survivor1
区或Survivor0
区中的对象的年龄计数器已经累加到15,将该对象转移到养老区
- 在养老区中内存不足时,会触发
Major GC
;如果进行GC后依旧无法保存对象,报OOM异常
注意:
Minor GC
是在Eden区满了才触发,Survivor0/1
区满了是不会触发Minor GC
,但是Minor GC
在回收的时候是将Eden区和Survivor0/1
区一起回收综上所述,整体流程如下图:
5.Minor GC、Major GC和Full GC
JVM进行GC时并不是每次对新生代、老年代和方法区一起回收。所以分为两个类型:
- 部分收集:
- Minor GC:只对新生代的GC
- Major GC:只对老年代的GC
- Mixed GC:对整个新生代以及部分老年代的GC
- 整堆收集(Full GC):对整个堆和方法区进行GC
- 部分收集:
Minor GC的触发:
- 年轻代空间(指Eden区,Survivor满时不触发GC)不足时
- 该GC速度快
- 该GC会导致STW(即暂停其他用户线程,等GC结束才恢复)
Major GC的触发:
- 老年代空间不足时,会先尝试Minor GC,空间还是不足就触发Major GC
- 该GC比Minor GC慢10倍,STW的时间也更长
Full GC的触发:
- 调用
System.gc()
- 老年代空间不足
- 方法区空间不足
- 通过Minir GC进入老年代的对象大小大于老年代可用内存
- 调用
6.为对象分配内存:TLAB
为什么有TLAB(
Thread Local Allocatuin Buffer
)?- 由于堆是线程共享区域,所以并发情况下在堆中创建对象是线程不安全的(因为不同线程可能在同一个堆中某部分内存上创建不同的对象)
- 加锁的话影响内存的分配速度
什么是TLAB?
- 在Eden区为每个线程分配一个私有的缓存区域TLAB
- 每个线程在各自的TLAB中创建对象
对象分配内存的过程:
边栏推荐
- 实例040:逆序列表
- Development of Taurus. MVC WebAPI introductory tutorial 1: download environment configuration and operation framework (including series directory).
- 深度学习(三)分类 理论部分
- [QNX Hypervisor 2.2用户手册]10.3 vdev gic
- 小程序+新零售,玩转行业新玩法!
- Pine Script | How to display and typeset a plot switch?
- 0.1 前言
- There are n steps in total, and you can go up to 1 or 2 steps each time. How many ways are there?
- Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。
- STM8S105k4t6c--------------点亮LED
猜你喜欢
实例036:算素数
C program compilation and predefined detailed explanation
Download install and create/run project for HBuilderX
2022年T电梯修理考题及答案
SAP SD模块前台操作
There are n steps in total, and you can go up to 1 or 2 steps each time. How many ways are there?
Snake game bug analysis and function expansion
2022焊工(初级)上岗证题目模拟考试平台操作
Example 035: Setting the output color
2022G1工业锅炉司炉考试练习题及模拟考试
随机推荐
简单排序(暑假每日一题 14)
STM8S-----选项字节
系统太多,多账号互通如何实现?
共n级台阶,每次可以上1级或2级台阶,有多少种上法?
Flutter3.0线程——四步教你如何全方位了解(事件队列)
【学习笔记之菜Dog学C】动态内存管理
Oracle迁移到瀚高之后,空值问题处理
Flink原理流程图简单记录
大佬们,读取mysql300万单表要很长时间,有什么参数可以优惠,或者有什么办法可以快点
uni-app 从零开始-基础模版(一)
[Original] Start the XPS/OXPS reader that comes with Windows 10
Engineering drawing review questions (with answers)
C language -- ring buffer
STM8S-----option byte
数据湖(二十):Flink兼容Iceberg目前不足和Iceberg与Hudi对比
What is SVN (Subversion)?
异步编程解决方案 Generator生成器函数、iterator迭代器、async/await、Promise
STM8S project creation (STVD creation) --- use COSMIC to create a C language project
WPE详细教程
There are too many systems, how to realize multi-account interworking?