深度解析:垃圾收集器与内存分配策略

GC需要完成的三件事情

哪些内存需要回收

什么时候回收

如何回收

在Java内存运行时区域的各个部分,其中程序计数器,虚拟机栈 本地方法栈 3个区域随着线程生,随着线程灭;栈中 的栈帧随着方法的进入和退出执行入栈和出栈的操作。每一个栈帧分配多少内存基本上在类结构确定下来 的时候就已经知道了,因此这几个区域的内存分配和回收都具备确定性,在这几个区域不考虑内存回收的问题,而堆和方法区不一样,一个接口多个实现类所需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间才能知道创建那些对象,这部分对象的分配和回收的动态的。

如何判断对象已死

  1. 引用计数法:每当一个地方引用他,计数器加1,引用失效计数器减一。 在大部分情况下是一个不错的算法,但是无法解决循环引用问题。
  2. 可达性分析算法:该算法的基本思路是 通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始往下搜索,搜索所走过的路径 称为链,当一个对象到GC roots 没有任何引用链,就证明这个对象不可用。

在JAVA中客作为GC roots的对象有以下几种,虚拟机栈中引用的对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI 引用的对象

引用

在jdk1.2之前 在java引用的定义很传统,导致对象只有两种状态被引用和没被引用的状态,无法描述一种状态如“食之无味,弃之可惜”的情况,我们希望能描述一个对象 当内存足够的时候,保留在内存中,如果内存紧张 则可以抛弃他们,在jdk1.2后将引用由细分为强引用,软引用,弱引用,虚引用等。

  • 强引用,只要强引用存在,垃圾收集器不会回收掉被引用的状态
  • 软引用,用来描述一些还有用,但并非必需的对象,在系统将要发生内存溢出异常之前,将会对这些对象进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。
  • 弱引用,强度比软引用还弱,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。乌云内存是否足够们都会被回收
  • 虚引用,它是最弱的引用,有无这个引用完全不对其生存时间构成影响,也无法通过虚引用来获取一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被垃圾收集器回收的时候收到一个系统通知。

生存还是死亡

当被可达性分析算法发现 一个对象 是不可达对象,不一定就会被回收宣告一个对象的死亡,至少需要经历两次标记。当对象被发现要被回收,会被第一次标记并进行筛选,筛选的条件是此对象是否有必要执行finalize()方法,当对象没有覆盖这个方法,或者这个方法已经被调研过了,会被视为没有必要执行,如果被判断需要执行的,会将对象放到一个F-Queue的队列中,并且稍后会由一个虚拟机自动建立,第优先级的Finalizer的线程去执行。(这里的执行指让虚拟机去触发这个机会,但并不承诺等待他运行结束,原因在于,对象如果在finalize方法中执行缓慢,或死循环,导致队列处于等待状态,会让内存回收系统崩溃),之后GC会对F-Queue中的对象进行第二次标记,如果对象在finalize有何其他对象建立关联,则会被移除即将回收的集合中,如果没有则就被真正回收 
注意事项 
任何一个对象的finalize方法只会背调用一次,如果面临下一次回收,他的finalize方法不会被执行。

回收方法区

方法区进行垃圾回收的性价比比较低。永久代的垃圾回收主要回收两个部分:废弃的常量和无用的类 
判断一个类是否是无用的类条件

  1. 该类的所有实例都已经被回收
  2. 加载该类的classload被回收
  3. 该类所对应的java.lang.class对象没有被任何地方引用,无法在任何地方通过反射访问该类的方法。

垃圾算法

  1. 标记-清除算法**,
    算法分为两个部分,一个是标记一个是清除,首先标记出所需要回收的部分,回收标记的对象,是一个最基础的收集算法,但是不足点有两个在于:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,清除后会出现大量不连续的内存碎片,如果出现大内存对象 需要再次提前出发垃圾回收操作来进行垃圾收集**的工作如图 

2.复制算法:
将内存分为大小相等的两块,每次只使用一块。当一块用完了,将还存在的对象复制到另一块上,然后再次吧使用过的内存一次清理掉,使得每次支队半个区域进行内存回收。按顺序分配内存,实现简单,运行高效,缺点在于将内存缩小为原先一半 

IBM的专门研究表明,新生代中的对象98%是朝生夕死的,所以并不需要按照1∶1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor当回收时,将Eden和Survivor中还存活着的对象一次性地拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1

也就是新生代为80+10 只有10的内存是浪费的,但是无法保障,只有不多与10的对象存活,如果空间不够需要到其他内存中进行分配担保。

3.标记-整理算法 
复制算法在对象存活率比较高的时候,进行较多的复制操作,效率会变低。如果不浪费一半的内存就需要而外的空间做担保,在老年代中不考虑用这种算法 
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

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

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

img

img

img

img

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

分享读者

作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!**

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值