美文网首页
内存优化

内存优化

作者: 放肆滴微笑 | 来源:发表于2019-11-19 16:14 被阅读0次

内存优化,主要来处理:内存泄露,内存抖动

Java虚拟机

运行时数据区域分为

  1. 共享数据区
    1.方法区
    • ClassLoader加载类信息,常量、静态变量、类信息,编译后的代码
    • 运行时常量池,字面量public static final java常量,符号引用,类,接口全名,方法名
    1. java堆
    • 虚拟机能管理的最大一块内存,gc主战场
    • 对象实例,数组的内容
  2. 线程私有区
    1. 程序计数器,相当于一个执行代码的指示器,用来确认下一行代码的地址,每个线程都会有一个。也就是一个变量,存储下一行代码的内存地址,如下绿色


      image.png
    2. 虚拟机栈,java虚拟机规范中定义了outofmemory和stackoverflow异常
    3. 本地方法栈,java虚拟机规范中定义了outofmemory和stackoverflow异常
image.png image.png

内存泄露

产生原因
一个长生命周期的对象持有一个短生命周期对象的引用,通俗讲就是该回收的对象,因为引用问题没有被回收,最终OOM

Android Profiler的使用

  1. Run菜单下的profile XXX 或者 image.png
  2. 在图型用户界面上选择要分析的一段内存
    • Allocations: 动态分配对象个数
    • Deallocation:解除分配的对象个数
    • Total count :对象的总数
    • Shallow Size:对象本身占用的内存大小
    • Retained Size:GC回收能收走的内存大小
      下载出来


      image.png

Mat工具使用
Mat下载地址

  1. 根据上面下载的文件,转换profile文件格式,打开sdk/platform-tools/hprof-conv文件,创建一个临时文件夹,cmd中找到,执行转换命令 hprof-conv -z 源文件 目标文件
  2. 打开文件 File-->Open Heap Dump...
  3. 选择Histogram


    image.png
  4. 输入查找的类名,就可以进行分析了
    image.png

解决方案

  • 如果是自己写的,则进行处理
  • 第三方写的,反射找到问题,处理

内存抖动

内存的频繁分配与回收,如果分配速度大于回收速度,最后也会OOM
标记清除算法Mark-Sweep


image.png

复制算法Copying


image.png

标记压缩算法Mark-Compact


image.png

强软弱虚引用

  • 强引用 不回收
  • 软引用 内存不足时回收,存放一些重要性不是很强又不能随便让清除的对象,比如图片切换到后台不需要马上显示了
  • 弱引用 第一次扫到了,就标记下来,第二次扫到直接回收
  • 虚引用 幽灵 幻影引用 不对生存造成任何影响,用于跟踪GC的回收通知

区别
虚引用只要gc扫过去,就会回收,是拿不到数据,只能从队列中获取
弱引用,可以拿到数据,gc扫过后拿不到数据,只能从队列中获取

# 虚引用
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
Object obj = new Object();
//虚引用
PhantomReference phantomReference = new PhantomReference(obj,referenceQueue);

//拿到虚引用的对象
System.out.println("phantomReference   obj:"+phantomReference.get());
//获取一个对象
System.out.println("referenceQueue   poll"+referenceQueue.poll());

obj = null;
System.gc();
Thread.sleep(2000);

//拿到虚引用的对象
System.out.println("phantomReference   obj:"+phantomReference.get());
//获取一个对象
System.out.println("referenceQueue   poll"+referenceQueue.poll());

通过打印发现,虚引用在放入引用中,就不能获取到对象,引用队列开始也不能获取,通过gc后,则引用无法获取对象,引用队列则记录了对象

phantomReference   obj:null
referenceQueue   pollnull
phantomReference   obj:null
referenceQueue   polljava.lang.ref.PhantomReference@32a1bec0

# 弱引用

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
Object obj = new Object();

WeakReference weakReference = new WeakReference(obj,referenceQueue);
//拿到弱引用的对象
System.out.println("weakReference   obj:"+weakReference.get());
//获取一个对象
System.out.println("referenceQueue   poll"+referenceQueue.poll());

obj = null;
System.gc();
Thread.sleep(2000);

//拿到弱引用的对象
System.out.println("weakReference   obj:"+weakReference.get());
//获取一个对象
System.out.println("referenceQueue   poll"+referenceQueue.poll());

通过打印 发现,弱引用在gc回收前,可以获得引用对象,引用队列中没有对象,gc后,不能获得引用对象,引用队列中可以获得之前的引用对象

weakReference   obj:java.lang.Object@32a1bec0
referenceQueue   pollnull
weakReference   obj:null
referenceQueue   polljava.lang.ref.WeakReference@22927a81

内存优化解决方案,编码习惯

  • 数据类型,不要使用必须求更占空间的基本类型,能用int则不用long,float比int站空间
  • 循环尽量用foreach,少用iterator,自动装箱少用
  • 数据量千级别以内,可以使用Sparse数组,(key为整数),ArrayMap(key为对象)
  • 枚举优化
    • 缺点:
      1、每一个枚举值都是一个单例对象,在使用它时会增加额外的内存消耗,所以枚举相比与 Integer 和 String 会占用更多的内存。
      2、较多的使用 Enum 会增加 DEX 文件的大小,会造成运行时更多的IO开销,使我们的应用需要更多的空间。
      3、特别是分dex多的大型APP,枚举的初始化很容易导致ANR
  • 改进将常量值变成
public static final int RECTANGLE=0;
public static final int TRIANGLE=1;
public static final int SQUARE=2;
public static final int CIRCLE=3;

//flag=true ,只能选择常量的一种负值不能| false 则可以|
@IntDef(flag=true,value={RECTANGLE,TRIANGLE,SQUARE,CIRCLE})
@Target({ElementType.PARAMETER,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Model{

}

private @Model int value=RECTANGLE;
public void setShape(@Model int value){
    this.value=value;
}
@Model
public int getShape(){
    return this.value;
}
  • static static final,static会由编译器调用clinit方法进行初始化
    static final不需要进行初始化工作,打包在dex文件中可以直接调用,并不会在类初始化申请内存
    所以基本数据类型的成员,可以全写成static final
  • 字符串的连接尽量少用加号(+) 使用StringBuffer
  • 循环中避免重复申请内存,对象放到循环外面
  • 避免GC回收之后还会用的对象,使用对象池来处理

相关文章

网友评论

      本文标题:内存优化

      本文链接:https://www.haomeiwen.com/subject/rekeictx.html