
内存抖动产生原因
当频繁的分配和回收内存时,由于回收的内存是不连续的,分配新内存时不能正好用尽回收的内存,就会存在小块空白的内存块.如果这种内存块越来越多,会导致可用内存有很多,但是不能分配一块连续的较大的内存块来创建对象,这时jvm就会报oom异常.
GC回收算法
-
标记清除算法Mark-Sweep
标记清除.png
GC第一次扫描时将可回收对象标记,第二次扫描直接回收.
-
复制算法Copying
image.png
jvm将内存分成两个相同的部分,每次使用其中的一部分,回收时将存活对象复制到另一部分,然后直接清除之前使用的内存.
-
标记压缩算法Mark-Compact
image.png
GC第一次扫描将可以收的对象进行标记,回收时将可回收的移向一边,存活的移向另一边,然后清除可回收一边的数据
-
分代回收机制
image.png
注意:Permanent和垃圾回收没什么关系,主要用来存放类,方法信息,也能作为常量沲使用,不同VM不同实现,有些没这个区
如上图
新分配的内存在新生代的EdenSpace,EdenSpace采用标记清理算法,当经过一次清理而没有被回收,就将存活的对象转移到SurvivorSpace,SurvivorSpace采用复制算法,将经过多次回收仍然存活的对象转移至老生代,老生代采用的是标记压缩算法.
优化内存的良好编码习惯

代码
- 枚举的改进
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;
}
}
- 自定义对象池
package com.dqchen.dndemo;
import android.util.SparseArray;
/**
* 对象池
* @param <T>
*/
public abstract class ObjectPool<T> {
private SparseArray<T> freePool;//空闲池
private SparseArray<T> 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());
}
网友评论