JAVA内存管理

​ 在java中,内存的分配是由程序类完成的,而内存的释放则是由 JAVA 的垃圾回收机制(GC) 来完成的,这种方式简化了程序员的工作,但是也加重了 JVM 的工作。这也是JAVA 程序运行比较慢的原因。

​ 为了能正确的释放对象,GC 必须监控每一个对象的运行状态,包括对象的申请,引用,赋值等,监控对象是为了能更加准确 的释放对象的内存。而释放对象的根本原则就是 该对象不在被引用

1,JAVA 内存分配策略、

​ Java 程序运行时的分配内存策略有三种,分别是静态分配,栈式分配和堆分配 。三种方式所使用的内存空间分别是静态存储区(方法区),栈区,和堆区。

  • 静态存储区(方法区):主要存放静态变量,这块【内存】在程序编译时就分配好了。并且在整个程序运行过程中都存在。
  • 栈区:当方法被执行是,方法体内的局部变量(包括基础的数据类型,对象的引用)都在栈上创建,当方法结束时,这些局部变量所持有的内存就会得到释放,因为栈内存分配运算内置于处理器的指令集中,所以效率很高,但是分配的内存容量有限。
  • 堆区:又称动态内存分配,通常就是指程序运行时直接new 出来的内存,也就是对象的实例,这部分【内存】在不使用时会被 java 垃圾回收机制 回收。

结论:

​ 局部变量的基本数据类型和引用存储于栈中,引用的对象实体存储在堆中,——因为他们属于方法中的变量,当方法结束时,对象也会随着方法而结束。

​ 成员变量全部存储于堆中(包括基本类型,引用和引用的对象实体) ——因为他们属于类,类对象是被 new 出来使用的。

2,Java 垃圾回收器。

​ 垃圾回收器的主要任务就是回收 已经不使用的对象。

判断对象是否存活的方法。
  • 引用计数法

    ​ 给对象添加一个计数器,当有一个地方引用他时,计数器就加 一,当引用失效是就 减一,任何时刻计数器为 0 的对象 就是不可再被 使用的。

    ​ 引用计数法的实现比较简单,判定的效率也很高,大部分情况下他都是一个不错的算法,但是主流的 java 虚拟机没有选用引用计数算法来管理内存,其中最主要的原因是 对象之间相互循环引用的问题。

  • 可达性分析算法

    ​ 这个算法的基本思想就是通过一系列称为【GC Roots】的对象作为起点,从这些节点向下开始搜索,搜索走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链 相连时,则证此对象是不可用的。

    ​ 在Java 中,可作为GC Roots 对象的包括下面几种

    • 虚拟机栈(栈中的本地变量),中引用的对象
    • 方法区中静态属性 引用的对象
    • 方法去中常量 引用的对象。
    • 本地方法栈 引用的对象。

3,垃圾回收算法

标记——清除算法

​ 最基础的就是 【标记 —— 清除】算法,分为 标记 和清除两个阶段。

  • 标记出所有需要回收的对象

  • 在标记完成后 统一回收所有被标记的算法。

    之所以说他是最基础的手机算法,是因为后续的所有算法都是基于这种思路,并对其不足改进出来的。

  • 效率问题,标记和清除 两个过程 的效率都不高

  • 空间问题,标记和清除之后会产生大量不连续的内存碎片

​ 内存碎片太多,可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

复制算法

​ 为了解决效率问题,一种称为「复制」的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

​ 这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半。

标记 —— 整理算法

​ 复制算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是,如果不想浪费 50 % 的空间,就需要有额外的空间进行担保,以应对被使用的内存中所有对象都 100% 存活的极端情况,所以在老年代一般不能直接选用这种算法。

根据老年代的特点,提出了另一种「标记 — 整理」算法,标记过程仍然与「标记 — 清理」算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。

分代收集发

​ 当前商业虚拟机的垃圾收集都采用「分代收集」算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块,一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。

​ 在新生代中,每次垃圾收集都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集,而老年代中因为对象存活率高、没有额外空间对它进行担保,就必须采用「标记 — 清理」或者「标记 — 整理」算法来回收

参考自:https://www.jianshu.com/p/8ad00f5b06be

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值