<内存泄漏=“ =” android =“”>

时间:2018-08-20 14:33:59

标签: android memory-leaks

在严格模式下似乎发生了内存泄漏

PathClassLoader pathClassLoader = new PathClassLoader(apkName, apkContext.getClassLoader());

loadExternalClass方法在应用程序的许多位置被调用

在获取下一次通话资源之前我们如何释放资源

private static Map<String, Class<?>> mCachedClasses = new HashMap<>();
public Class<?> loadExternalClass(String packageName, String className)
            throws NameNotFoundException, ClassNotFoundException {


        String key = packageName+"/"+className;

        if (!mCachedClasses.containsKey(key)) {
            // Dynamic class loading from different apk
            Context apkContext = loadExternalContext(packageName);
        String apkName = apkContext.getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
            PathClassLoader pathClassLoader = new PathClassLoader(apkName, apkContext.getClassLoader());
            Class<?> clazz = Class.forName(className, true, pathClassLoader);
            mCachedClasses.put(key, clazz);

        }

        return mCachedClasses.get(key);
    }

08-15 13:17:22.257 E/StrictMode( 1761): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.

08-15 13:17:22.257 E/StrictMode( 1761): java.lang.Throwable: Explicit termination method 'close' not called

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.CloseGuard.open(CloseGuard.java:184)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.DexFile.<init>(DexFile.java:80)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.DexFile.<init>(DexFile.java:57)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.DexPathList.loadDexFile(DexPathList.java:256)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.DexPathList.makeDexElements(DexPathList.java:223)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.DexPathList.<init>(DexPathList.java:106)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:46)

08-15 13:17:22.257 E/StrictMode( 1761):     at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)

08-15 13:17:22.257 E/StrictMode( 1761):     at com.cnh.android.windowmanager.util.WmUtils.loadExternalClass(WmUtils.java:249)

我尝试了一个Dummy应用程序,并尝试最终组合以释放资源,但它在同一时刻仍然给出相同的错误

public class MainActivity_leak extends AppCompatActivity {
    private Context mContext;
    public String packageName= "com.test.android.device";
    public String className = "com.test.android.device.elements.UpperDrawerButton" ;

    public int i = 0;
    private static Map<String,  Class<?> > mCachedClasses = new HashMap<>();

    private static Map<String, Context> mCachedContexts = new HashMap<>();
    public MainActivity_leak(){

    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_leak);

        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .penaltyFlashScreen()
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectAll()
                .penaltyLog()
              .build());
        Log.w("", "Strict mode enabled");
        mContext = this.getApplicationContext();
        try {
            for (int i =0 ; i<10000 ; i++)
                     {
                      View view = loadExternalView(packageName,className);
            }

        } catch (PackageManager.NameNotFoundException e) {

            e.printStackTrace();
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        } catch (InstantiationException e) {

            e.printStackTrace();
        } catch (IllegalAccessException e) {

            e.printStackTrace();
        } catch (InvocationTargetException e) {

            e.printStackTrace();
        } catch (NoSuchMethodException e) {

            e.printStackTrace();
        }
    }
       public Class<?> loadExternalClass(String packageName, String className)
            throws PackageManager.NameNotFoundException, ClassNotFoundException {

        String key =null;
        Context apkContext = null;
        String apkName = null;
        PathClassLoader pathClassLoader =null;
        Class<?> clazz = null;
        try {
            key = packageName + "/" + className;    
        if (!mCachedClasses.containsKey(key)) {
           apkContext = loadExternalContext(packageName);
            apkName = apkContext.getPackageManager().getApplicationInfo(packageName, 0).sourceDir;

            pathClassLoader = new PathClassLoader(apkName, apkContext.getClassLoader());


            clazz = Class.forName(className, true, pathClassLoader);
                mCachedClasses.put(key, clazz);

        }

            return mCachedClasses.get(key);
        }finally{
            if (apkContext != null) {
                apkContext.deleteFile(packageName);
                apkContext=null;
                pathClassLoader = null;
                key = null;
                apkName = null;
            }

        }
    }
    public synchronized Context loadExternalContext(String packageName)
            throws PackageManager.NameNotFoundException, NullPointerException {


        if (!mCachedContexts.containsKey(packageName)) {

            Context context = mContext.createPackageContext(packageName, CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY);
            mCachedContexts.put(packageName, context);
        }
        return mCachedContexts.get(packageName);
    }
   public synchronized View loadExternalView(String packageName, String className)
            throws PackageManager.NameNotFoundException, ClassNotFoundException, ClassCastException, IllegalArgumentException, InstantiationException,
            IllegalAccessException, InvocationTargetException, NoSuchMethodException, NullPointerException {

        Context apkContext = loadExternalContext(packageName);
        Class<?> cls = loadExternalClass(packageName, className);
        clearInflaterCache(apkContext);   
        return (View) cls.getConstructor(Context.class).newInstance(apkContext);
    }

    public static void clearInflaterCache(Context context) {
        try {

            Field ctorMapField = LayoutInflater.class.getDeclaredField("sConstructorMap");
            ctorMapField.setAccessible(true);
            @SuppressWarnings("unchecked")
            HashMap<String, Constructor<? extends View>> ctorMap = (HashMap<String, Constructor<? extends View>>)
                    ctorMapField.get(LayoutInflater.from(context));
            Iterator<String> i = ctorMap.keySet().iterator();
            while (i.hasNext()) {
                String name = i.next();
                if (name.startsWith("com.test")) i.remove();
            }
        } catch (Exception e) {

        }
    }

}

D/dalvikvm( 3344): GC_CONCURRENT freed 291K, 8% free 4542K/4908K, paused 3ms+3ms, total 104ms

E/StrictMode( 3344): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.

E/StrictMode( 3344): java.lang.Throwable: Explicit termination method 'close' not called

E/StrictMode( 3344):    at dalvik.system.CloseGuard.open(CloseGuard.java:184)

E/StrictMode( 3344):    at dalvik.system.DexFile.<init>(DexFile.java:80)

E/StrictMode( 3344):    at dalvik.system.DexFile.<init>(DexFile.java:57)

E/StrictMode( 3344):    at dalvik.system.DexPathList.loadDexFile(DexPathList.java:256)

E/StrictMode( 3344):    at dalvik.system.DexPathList.makeDexElements(DexPathList.java:223)

E/StrictMode( 3344):    at dalvik.system.DexPathList.<init>(DexPathList.java:106)

E/StrictMode( 3344):    at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:46)

E/StrictMode( 3344):    at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)

E/StrictMode( 3344):    at com.example.a287470.myapplication_leak.MainActivity_leak.loadExternalClass(MainActivity_leak.java:130)

E/StrictMode( 3344):    at com.example.a287470.myapplication_leak.MainActivity_leak.loadExternalView(MainActivity_leak.java:172)

0 个答案:

没有答案