Android内存基础——Java内存管理机制

本文深入探讨Java内存管理机制,解析代码段、数据段、堆栈段及堆段的作用与区别,重点阐述堆段中年轻代与老年代的运作原理及垃圾回收机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接

参考资料1

背景介绍

  • Java优势之一就是其具有垃圾回收机制。在大部分情况下,JVM的GC(垃圾回收器)能够帮助我们回那些不可到达的对象(就是未被引用的对象)。
  • 当然,在一些情况下,我们仍然需要自己去释放内存(就是把对象置null,把容器、数组清空),否则就会引起内存泄漏,内存泄漏严重时将容易引发OutOfMemoryError,详情见内存泄漏
  • 此外,由于GC会停止所有的线程,包括UI线程,所以频繁的GC必然会导致画面卡顿(Android中每16ms为一帧),因此还应避免GC的频繁发生。一个导致GC频繁发生的原因就是内存抖动,点击链接看详情。
    GC时线程被停止示意图
  • 所以,理解Java的内存机制,有助于帮助我们在写代码的过程中避免内存泄漏。

基本概念

Java内存层级

Created with Raphaël 2.1.0 Code Segment:存放代码 Data Segment:存放静态变量,方法 Stack Segment:存放变量,即引用 Heap Segment:存放非静态对象

Heap Segment

Java8之后,Heap Segment真正意义上的是由Young GeneriationOld Generiation组成的。对象在其中是标记复制算法来判定一个对象是否应该被清理掉。
Heap Segment中发生的GC称为Major GC,只会影响Heap Segment区。
内存图

Young Generiation中的GC变化

  • 当对象被创建后,首先会被加入eden区。当eden区满了之后,就会触发一次GC,存活下来的对象会被复制到survivor区。
  • 当不为空的Survivor区满了,同样会触发一次GC。
  • 当短时间内有大量对象创建和释放同样会造成内存抖动,会触发CG。
  • 如图所示,survivor有两个区域,其中一个总是保持为空。
  • 现假设两个Survivor区分别为S0,S1,并且首次GC时,eden区中存活的对象被复制到S0中。当再次发生GC时,S0和eden中仍然存活的对象就会被复制到空的S1中,此时S0为空;再次发生GC时,S1和eden中存活的对象将被复制到S0中,此时S1为空;再次发生GC…就是这样进行的。当一个对象被来回复制转移的次数达到阀值(默认为15次,可以通过使用-XX:MaxTenuringThreshold该命令来调整阀值)时,这个对象将被复制到Old Generiation区中,此时该对象将会变的相对安全,因为Old Segment区的GC频率相对较低。

Old Segment中的GC变化

  • 该区域满了之后会触发一次GC,在该次GC中,一些年龄较大的对象会被清理掉。
  • 若多次触发GC后,该区域仍然处于满的状态,则会抛出OutOfMemoryError
  • 以两种情况下,新建对象会被直接复制到该区域中:
    • 当新建对象所需要的内存大于1/2的单个survivor区内存时;
    • 当新建对象被该区中的对象引用时,或者引用了该区域中的对象。

总结

  • Java内存块被划分为:Code SegmentDataSegmentStackSegmentHeap Segment,其中Heap Segment由于设计对象的创建与销毁,所以它应该重点关注的对象。
  • Heap Segment又被划分为两块:Young GeneriationOld Generiation
  • Young Genertiation中又被划分为Eden区和两个Survivor区,对象在其中采用标记复制算法来判定一个对象是应该清理还是移到Old Generiation中。该内存区域发生GC的频率较高。
  • Old Generiation发生GC的频率相对较低。当有大对象被创建,或者和该区域有关的对象被创建时,它将会被直接移动到该区域中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值