本文作为个人笔记,吸取采纳各位大神的精华,作为个人开发注意事项,仅在CSDN保存。
1.Context的用法
举例:单利模式(非线程安全)
public class Singleton {
private static Singleton instance;
private Context mContext;
private Singleton(Context context) {
this.mContext = context;
}
public static Singleton getInstance(Context context) {
if (instance == null) {
instance = new Singleton(context);
}
return instance;
}
}
这是一个非线程安全的单例模式,instance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,假如Activity A去getInstance获得instance对象,传入this,常驻内存的Singleton保存了你传入的Activity A对象,并一直持有,即使Activity被销毁掉,但因为它的引用还存在于一个Singleton中,就不可能被GC掉,这样就导致了内存泄漏。
注意事项:
一般Context造成的内存泄漏,几乎都是当Context销毁的时候,却因为被引用导致销毁失败,而Application的Context对象可以理解为随着进程存在的,所以我们总结出使用Context的正确姿势:
1:当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。
2:不要让生命周期长于Activity的对象持有到Activity的引用。
3:尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。
2.Class加载过程之自定义ClassLoader
/**
* 自定义文件类加载器
*/
public class FileSystemClassLoader extends ClassLoader {
private String rootDir;
public FileSystemClassLoader(String rootDir){
this.rootDir = rootDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> loadedClass = findLoadedClass(name);
if(null != loadedClass){
return loadedClass;
}else{
ClassLoader classLoader = this.getParent();
try{
loadedClass = classLoader.loadClass(name);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
if(null != loadedClass){
return loadedClass;
}else{
byte[] classData = getClassData(name);
if(classData == null){
throw new ClassNotFoundException();
}else {
loadedClass = defineClass(name,classData,0,classData.length);
}
}
}
return loadedClass;
}
private byte[] getClassData(String name){
String path = rootDir+"/"+name.replace('.','/')+".class";
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = new FileInputStream(path);
byte[] bytes = new byte[1024];
int temp = 0;
while ((temp = is.read(bytes)) != -1){
baos.write(bytes,0,temp);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if(baos != null){
baos.close();
}
if(is != null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
definclass()
把字节码转化为Class
findClass()
- 根据名称或位置加载.class字节码,然后使用defineClass
- 通常由子类去实现
loadClass()
-
findLoadedClass(String) 调用这个方法,查看这个Class是否已经别加载
-
如果没有被加载,继续往下走,查看父类加载器,递归调用loadClass()
-
如果父类加载器是null,说明是启动类加载器,查找对应的Class
-
如果都没有找到,就调用findClass(String)