深入理解JVM的内存结构及GC机制,内容太过真实

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

image.png

其中,方法区和堆所有线程共享。

2.1 方法区(Method Area)

方法区存放了要加载的类的信息(如类名、修饰符等)、静态变量、构造函数、final定义的常量、类中的字段和方法等信息。方法区是全局共享的,在一定条件下也会被GC。当方法区超过它允许的大小时,就会抛出OutOfMemory:PermGen Space异常。

在Hotspot虚拟机中,这块区域对应持久代(Permanent Generation),一般来说,方法区上执行GC的情况很少,因此方法区被称为持久代的原因之一,但这并不代表方法区上完全没有GC,其上的GC主要针对常量池的回收和已加载类的卸载。在方法区上进行GC,条件相当苛刻而且困难。

**运行时常量池(Runtime Constant Pool)**是方法区的一部分,用于存储编译器生成的常量和引用。一般来说,常量的分配在编译时就能确定,但也不全是,也可以存储在运行时期产生的常量。比如String类的intern()方法,作用是String类维护了一个常量池,如果调用的字符"hello"已经在常量池中,则直接返回常量池中的地址,否则新建一个常量加入池中,并返回地址。

2.2 堆区(Heap)

堆区是GC最频繁的,也是理解GC机制最重要的区域。堆区由所有线程共享,在虚拟机启动时创建。堆区主要用于存放对象实例及数组,所有new出来的对象都存储在该区域。

2.3 虚拟机栈(VM Stack)

虚拟机栈占用的是操作系统内存,每个线程对应一个虚拟机栈,它是线程私有的,生命周期和线程一样,每个方法被执行时产生一个栈帧(Statck Frame),栈帧用于存储局部变量表、动态链接、操作数和方法出口等信息,当方法被调用时,栈帧入栈,当方法调用结束时,栈帧出栈。

局部变量表中存储着方法相关的局部变量,包括各种基本数据类型及对象的引用地址等,因此他有个特点:内存空间可以在编译期间就确定,运行时不再改变。

虚拟机栈定义了两种异常类型StackOverFlowError(栈溢出)和OutOfMemoryError(内存溢出)。如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StackOverFlowError;不过大多数虚拟机都允许动态扩展虚拟机栈的大小,所以线程可以一直申请栈,直到内存不足时,抛出OutOfMemoryError。

2.4 本地方法栈(Native Method Stack)

本地方法栈用于支持native方法的执行,存储了每个native方法的执行状态。本地方法栈和虚拟机栈他们的运行机制一致,唯一的区别是,虚拟机栈执行Java方法,本地方法栈执行native方法。在很多虚拟机中(如Sun的JDK默认的HotSpot虚拟机),会将虚拟机栈和本地方法栈一起使用。

2.5 程序计数器(Program Counter Register)

程序计数器是一个很小的内存区域,不在RAM上,而是直接划分在CPU上,程序猿无法操作它,它的作用是:JVM在解释字节码(.class)文件时,存储当前线程执行的字节码行号,只是一种概念模型,各种JVM所采用的方式不一样。字节码解释器工作时,就是通过改变程序计数器的值来取下一条要执行的指令,分支、循环、跳转等基础功能都是依赖此技术区完成的。

每个程序计数器只能记录一个线程的行号,因此它是线程私有的。

如果程序当前正在执行的是一个java方法,则程序计数器记录的是正在执行的虚拟机字节码指令地址,如果执行的是native方法,则计数器的值为空,此内存区是唯一不会抛出OutOfMemoryError的区域。

三、GC机制

随着程序的运行,内存中的实例对象、变量等占据的内存越来越多,如果不及时进行回收,会降低程序运行效率,甚至引发系统异常。

在上面介绍的五个内存区域中,有3个是不需要进行垃圾回收的:本地方法栈、程序计数器、虚拟机栈。因为他们的生命周期是和线程同步的,随着线程的销毁,他们占用的内存会自动释放。所以,只有方法区和堆区需要进行垃圾回收,回收的对象就是那些不存在任何引用的对象。

3.1 查找算法

经典的引用计数算法,每个对象添加到引用计数器,每被引用一次,计数器+1,失去引用,计数器-1,当计数器在一段时间内为0时,即认为该对象可以被回收了。但是这个算法有个明显的缺陷:当两个对象相互引用,但是二者都已经没有作用时,理应把它们都回收,但是由于它们相互引用,不符合垃圾回收的条件,所以就导致无法处理掉这一块内存区域。因此,Sun的JVM并没有采用这种算法,而是采用一个叫——根搜索算法,如图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

image.png

基本思想是:从一个叫GC Roots的根节点出发,向下搜索,如果一个对象不能达到GC Roots的时候,说明该对象不再被引用,可以被回收。如上图中的Object5、Object6、Object7,虽然它们三个依然相互引用,但是它们其实已经没有作用了,这样就解决了引用计数算法的缺陷。

补充概念,在JDK1.2之后引入了四个概念:强引用、软引用、弱引用、虚引用
强引用:new出来的对象都是强引用,GC无论如何都不会回收,即使抛出OOM异常。
软引用:只有当JVM内存不足时才会被回收。
弱引用:只要GC,就会立马回收,不管内存是否充足。
虚引用:可以忽略不计,JVM完全不会在乎虚引用,你可以理解为它是来凑数的,凑够"四大天王"。它唯一的作用就是做一些跟踪记录,辅助finalize函数的使用。

最后总结,什么样的类需要被回收:

a.该类的所有实例都已经被回收;
b.加载该类的ClassLoad已经被回收;
c.该类对应的反射类java.lang.Class对象没有被任何地方引用。

3.2 内存分区

内存主要被分为三块:新生代(Youn Generation)、旧生代(Old Generation)、持久代(Permanent Generation)。三代的特点不同,造就了他们使用的GC算法不同,新生代适合生命周期较短,快速创建和销毁的对象,旧生代适合生命周期较长的对象,持久代在Sun Hotpot虚拟机中就是指方法区(有些JVM根本就没有持久代这一说法)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

image.png

新生代(Youn Generation):大致分为Eden区和Survivor区,Survivor区又分为大小相同的两部分:FromSpace和ToSpace。新建的对象都是从新生代分配内存,Eden区不足的时候,会把存活的对象转移到Survivor区。当新生代进行垃圾回收时会出发Minor GC(也称作Youn GC)。

旧生代(Old Generation):旧生代用于存放新生代多次回收依然存活的对象,如缓存对象。当旧生代满了的时候就需要对旧生代进行回收,旧生代的垃圾回收称作Major GC(也称作Full GC)。

持久代(Permanent Generation):在Sun 的JVM中就是方法区的意思,尽管大多数JVM没有这一代。

3.3 GC算法

常见的GC算法复制、标记-清除和标记-压缩

复制:复制算法采用的方式为从根集合进行扫描,将存活的对象移动到一块空闲的区域,如图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

Android开发除了flutter还有什么是必须掌握的吗?

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

[外链图片转存中…(img-1gjnO7v4-1711878711131)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值