性能优化(四,内存抖动)

性能优化(四,内存抖动)_第1张图片
images.jpg
内存抖动产生原因

当频繁的分配和回收内存时,由于回收的内存是不连续的,分配新内存时不能正好用尽回收的内存,就会存在小块空白的内存块.如果这种内存块越来越多,会导致可用内存有很多,但是不能分配一块连续的较大的内存块来创建对象,这时jvm就会报oom异常.

GC回收算法
  1. 标记清除算法Mark-Sweep


    性能优化(四,内存抖动)_第2张图片
    标记清除.png

    GC第一次扫描时将可回收对象标记,第二次扫描直接回收.

  2. 复制算法Copying


    性能优化(四,内存抖动)_第3张图片
    image.png

jvm将内存分成两个相同的部分,每次使用其中的一部分,回收时将存活对象复制到另一部分,然后直接清除之前使用的内存.

  1. 标记压缩算法Mark-Compact


    性能优化(四,内存抖动)_第4张图片
    image.png

    GC第一次扫描将可以收的对象进行标记,回收时将可回收的移向一边,存活的移向另一边,然后清除可回收一边的数据

  2. 分代回收机制


    性能优化(四,内存抖动)_第5张图片
    image.png

    注意:Permanent和垃圾回收没什么关系,主要用来存放类,方法信息,也能作为常量沲使用,不同VM不同实现,有些没这个区
    如上图
    新分配的内存在新生代的EdenSpace,EdenSpace采用标记清理算法,当经过一次清理而没有被回收,就将存活的对象转移到SurvivorSpace,SurvivorSpace采用复制算法,将经过多次回收仍然存活的对象转移至老生代,老生代采用的是标记压缩算法.

优化内存的良好编码习惯
性能优化(四,内存抖动)_第6张图片
image.png
代码
  1. 枚举的改进
package com.dqchen.dndemo;

import android.support.annotation.IntDef;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 枚举类型转换
 */
public class Shape {
    public static final int RECTANGLE = 0;
    public static final int TRIANGLE = 1;
    public static final int SQUARE = 2;
    public static final int CIRCLE = 3;

    @IntDef(flag = true,value = {RECTANGLE,TRIANGLE,SQUARE,CIRCLE})
    @Target({ElementType.METHOD,ElementType.PARAMETER,ElementType.FIELD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Modle{}

    public @Modle int value = RECTANGLE;
    public void setShape(@Modle int vale){
        this.value = vale;
    }

    public int getShape(){
        return this.value;
    }
}

  1. 自定义对象池
package com.dqchen.dndemo;

import android.util.SparseArray;

/**
 * 对象池
 * @param 
 */
public abstract class ObjectPool {

    private SparseArray freePool;//空闲池
    private SparseArray lentPool;//正在使用的池
    private int maxCapacity;

    public ObjectPool(int initializeCapacity,int maxCapacity){
        this.maxCapacity = maxCapacity;
        initialize(initializeCapacity);
    }

    private void initialize(int maxCapacity) {
        freePool = new SparseArray<>();
        lentPool = new SparseArray<>();
        for (int i = 0; i < maxCapacity; i++) {
            freePool.put(i,create());
        }
    }

    protected abstract T create();

    /**
     * 申请对象
     * @return
     */
    public T acquire() throws Exception{
        T t = null;
        int freeSize = freePool.size();
        for (int i = 0; i < freeSize; i++) {
            int key = freePool.keyAt(i);
            t = freePool.get(key);
            if (t!=null){
                freePool.remove(key);
                lentPool.put(key,t);
            }
            return t;
        }

        if (t==null && freeSize+lentPool.size() < maxCapacity){

            if (freeSize+lentPool.size()==maxCapacity){
                throw new Exception();
            }

            t = create();
            lentPool.put(freeSize+lentPool.size(),t);
        }
        return t;
    }

    /**
     * 回收对象
     * @param t
     */
    public void remove(T t){
        if (t==null){
            return;
        }
        int key = lentPool.indexOfValue(t);

        restore(t);//回收前给用户留个操作

        lentPool.remove(key);
        freePool.put(key, t);

    }

    protected abstract void restore(T t);

    public ObjectPool(int maxCapacity){
        this(maxCapacity/2,maxCapacity);
    }
}
package com.dqchen.dndemo;

public class MyObjectPool extends ObjectPool {
    public MyObjectPool(int initialCapacity, int maxCapacity) {
        super(initialCapacity, maxCapacity);
    }

    public MyObjectPool(int maxCapacity) {
        super(maxCapacity);
    }

    @Override
    protected Object create() {
        return new Object();//LRU
    }

    @Override
    protected void restore(Object o) {

    }
}
    private void testObjPool() throws Exception {

        MyObjectPool objectPool = new MyObjectPool(4);
        Object o1 = objectPool.acquire();
        Object o2 = objectPool.acquire();
        Object o3 = objectPool.acquire();
        Object o4 = objectPool.acquire();

        Log.i("dqchen"," "+o1.hashCode());
        Log.i("dqchen"," "+o2.hashCode());
        Log.i("dqchen"," "+o3.hashCode());
        Log.i("dqchen"," "+o4.hashCode());

    }

你可能感兴趣的:(性能优化(四,内存抖动))