文章目录
1 简介
垃圾回收(GC)是由 Java 虚拟机(JVM)垃圾回收器提供的一种对内存回收的一种机制,它一般会在内存空闲或者内存占用过高的时候对那些没有任何引用的对象不定时地进行回收。
2 模型
-
JVM内存模型 (5种): 栈、本地方法栈、程序计数器、堆、方法区。
-
线程私有:虚拟机栈、本地方法栈和程序计数器。
-
线程共享:堆,方法区 所有线程能访问这块内存数据,是我们需要重点关注的对象,这两个区域主要存放对象、数组等不具有确定性的数据。比如方法运行的过程中创建的对象的数量是不确定的,对象的创建与否,需要一套合理的内存管理机制来对这两个区域进行维护(垃圾回收)
-
虚拟机栈其实就是用来描述 Java 方法执行的,所以每个方法执行的时候都会创建一个栈帧,当方法执行完成之后,对应的栈帧便会出栈。所以它的内存分配是具备确定性的,所以我们并不需要太过关注包括虚拟机栈在内的这几个线程私有区域的内存使用情况。
注:栈帧包含:局部变量、操作数栈、动态链接、方法出口。JDK 1.8之前
JDK1.8 之后
3 JVM判断对象是否存活的算法
- 引用计数算法
- 可达性分析算法
引用计数算法
一个对象被创建之后,系统会给该对象初始化一个引用计数器,当该对象被引用了,则计数器 +1,而当该引用失效后,计数器便 -1,直到计数器为 0,意味着该对象不再被使用了,则可以将其进行回收了。
优缺点
优点
- 好用
- 判定比较简单
- 效率也很高
缺点
- 无法避免循环引用,即两个对象之间循环引用的时候,各自的计数器始终不会变成 0。
引用计数算法 只出现在了早期的 JVM 中,现在基本不再使用了。
可达性分析算法
(根搜索算法)从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点,无用的节点将会被判定为是可回收的对象。
可以作为根对象
- 栈中引用的对象(局部变量表当中引用的对象)
- 类静态属性引用的对象
- 常量引用的对象
- Native 方法引用的对象
4.什么时候进行回收
- 会在cpu空闲的时候自动进行回收
- 在堆内存存储满了之后
- 主动调用System.gc()后尝试进行回收
5 Java 中的引用
6 finalize 方法
finalize:Object 的一个用于通知对象回收的方法,可在此处释放资源。
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
但是在某些特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。 使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
7.垃圾回收算法
- 标记清除法
- 复制算法
- 标记整理算法
标记清除法
当垃圾回收器将内存扫码之后会标记出所有垃圾对象,然后将它们回收。会产生大量的“碎片”,使内存的使用率越来越低。复制算法
准备两块一模一样的内存,当第一块内存剩余不足时,将所有保留的对象拷贝至另一块内存中,然后将第一块内存直接清空。内存空间浪费一倍。标记整理算法
在清理垃圾的基础上,多了一步碎片整理的工作。不适合高频率的执行。
总结 Android性能优化需要考虑的方面
App启动流程
Android之启动优化
Android之图片压缩几种方式
Android 通过采样率压缩图片
Android 内存泄漏
Android 之 Handler
Java引用类型(强引用,软引用,弱引用,虚引用)
Java List、Set、Map区别
Java 之 String、StringBuffer与StringBuilder 区别