本文作为个人笔记,吸取采纳各位大神的精华,作为个人开发注意事项,仅在保存。
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)