2 JVM的内存管理(堆内存)

我用思维导图对JVM的内存结构做简单的划分,如下图所示:
在这里插入图片描述

下面我们对各个区进行说明。

堆:

也称heap堆区。堆是jvm内存中占用空间最大的一个区域。主要分为新生代、老年代、永久代(jdk1.8以后叫元空间,到1.9以后又被移除)

新生代:
在new一个对象时,会把堆新生代的内存空间进行判断,如果内存空间够则放入新生代(如果是大对象,例如数据很多的容器对象,有可能直接放入老年代)。如果内存空间不够放入该对象,则
触发young gc,如果触发15次新生代空间还不够则把之前使用的数据迁移到老年代并释放新生代所有的空间。如果老年代的空间不够用,则进行full gc。如果老年代内存也不够用则抛出OOM
并结束线程。
gc的种类:
minor GC(又叫young GC):用于收集年轻代中的非存活对象,在新生代空间不足时触发,young gc 可能会触发线程暂停。所以在一些并发比较高或者集中处理一些行为中java会出现卡顿的现象就是出于这个原因

major gc:在老年代空间不足时触发。full gc的效率比较低,应尽量减少full gc的发生。目前只有CMS收集器有单独收集老年代的行为

mixed GC(混合收集):主要收集年轻代和部分老年代的非存活对象。目前G1收集器采用这种行为。

full gc:主要收集整个堆(新生代和老年代)中的非存活对象。System.gc()调用时候会触发full gc 。我们可以通过-XX:DisableExplicitGC来禁止System.gc()的行为。

在多次young gc后把新生代存活的对象迁移到老年代(在一定条件下才会触发。更加详细的信息可参阅《hotspot实战》由于篇幅有限不在这里详述),如果老年代空间不足时会触发full gc。
full gc后老年代内存还是不够用则OOM

我们看下新生代的内存分配,如下图:
在这里插入图片描述

对象的分配过程:
新生成的对象在年轻代Eden区中分配内存,当Eden空间已满时,触发Minor GC,将不再被其他对象所引用的对象进行回收,存活下来的对象被转移到Survivor0区。
Survivor0区满后触发Minor GC,将Survivor0区存活下来的对象转移到Survivor1区,同时,清空Survivor0区,保证总有一个Survivor区为空。
经过多次Minor GC后,仍然存活的对象被转移到老年代,进入老年代的Minor GC次数可以通过参数-XX:MaxTenuringThreshold=进行设置,默认为15次。
当老年代已满时会触发Major GC(即:Full GC,因此执行Major GC时会先执行Minor GC)。
分代收集的原因:将对象按照存活概率进行分类,主要是为了减少扫描范围和执行GC的频率,同时,对不同区域采用不同的回收算法,提高回收效率。
年轻代中存在两块相同大小的Survivor区的原因:解决内存碎片化,即:保证分配对象(如:大对象)时有足够的连续内存空间。

对象进入老年代的触发条件:

对象的年龄达到15岁时。默认的情况下,对象经过15次Minor GC后会被转移到老年代中。对象进入老年代的Minor GC次数可以通过JVM参数:-XX:MaxTenuringThreshold进行设置,默认为15次。
动态年龄判断。当一批存活对象的总大小超过Survivor区内存大小的50%时,按照年龄的大小(年龄大的存活对象优先转移)将部分存活对象转移到老年代中。
大对象直接进入老年代 。当需要创建一个大于年轻代剩余空间的对象(如:一个超大数组)时,该对象会被直接存放到老年代中,可以通过参数-XX:PretenureSizeThreshold(默认值是0,即:任何对象都会先在年轻代分配内存)进行设置。
Minor GC后的存活对象太多无法放入Survivor区时, 会将这些对象直接转移到老年代中。

字符串常量池:

字符串常量池是Java中的一个特殊的存储区域,用于存储字符串常量。在Java中,字符串常量是不可变的,因此可以被共享。这样可以减少内存的使用,提高程序的性能。在JDK8中,字符串常量池存储在堆中。

静态变量:

静态变量是指在类中定义的变量,它们的值在整个程序运行期间都不会改变。在JDK8中取消了永久代,方法区变成了一个逻辑上的区域,因此,静态变量的内存在堆中进行分配(JDK7及以前,静态变量的内存在永久代中进行分配)。它们的生命周期与类的生命周期相同。

线程本地缓冲区:
tlab
TLAB(Thread Local Allocation Buffer)是Java虚拟机中的一个优化技术,主要用于提高对象的分配效率。每个线程都有自己的TLAB,用于分配对象。当一个线程需要分配对象时,它会先在自己的TLAB中分配,如果TLAB中的空间不足,则会向堆中申请空间。

上面对内存的堆区进行了阐述。由于不同的jdk版本处理内存的方式不一样,会有些出入敬请谅解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值