码迷,mamicode.com
首页 > 其他好文 > 详细

被用坏的DexClassLoader,关于DexClassLoader内存泄露的问题

时间:2015-03-04 11:14:09      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

原因:

目前有两种猜测,第一种就是类加载容易,但是类卸载就不那么容易了,第二种猜测就是类缓存机制,从classloader的运行过程可以分析到有个过程是缓存常用类的,感觉这个过程没法释放,因为他会认为你以后会一直用。

测试内存泄露代码:

可以用DDMS测试下,当你调用GC的时候byte是可以回收的,但是classloader就没法回收了,也许你认为是因为调用了activity的classloader造成的,但是回头想想这个classloader可是整个应用的,除非你关闭应用,否则无法去掉classloader的引用。
package com.example.test04;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.channels.FileChannel;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import dalvik.system.DexClassLoader;

public class MainActivity extends Activity implements OnClickListener {
	Button test;
	Button test1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		test = (Button) findViewById(R.id.test);
		test.setOnClickListener(this);

		test1 = (Button) findViewById(R.id.test1);
		test1.setOnClickListener(this);

	}

	@Override
	public void onClick(View v) {
		if (v.equals(test)) {
			LoadClass();
		} else if (v.equals(test1)) {
			LoadData();
		}
	}

	private void LoadData() {
		if (progressDialog == null) {
			progressDialog = new ProgressDialog(this);
		}
		progressDialog.show();
		byte[] buffer = new byte[128 * 1024];
		progressDialog.hide();
	}

	ProgressDialog progressDialog;

	@SuppressLint("NewApi")
	private void LoadClass() {
		if (progressDialog == null) {
			progressDialog = new ProgressDialog(this);
		}
		progressDialog.show();
		try {
			String path = getFilesDir().getAbsolutePath() + File.separator;
			File source = new File(Environment.getExternalStorageDirectory() + "/Test03.apk");
			File target = new File(path + "Test03.apk");
			String targetpath = target.getAbsolutePath();
			if (!target.exists()) {
				copyFile(source, target);
			}
			WeakReference<ClassLoader> reference = new WeakReference<ClassLoader>(getClassLoader());
			DexClassLoader classLoader = new DexClassLoader(targetpath, path, null, reference.get());
			// 加载到了类
			Class<?> mClass = classLoader.loadClass("com.test.Root");
		} catch (Exception e) {

		}
		progressDialog.hide();
	}

	/**
	 * 
	 * 复制文件
	 * 
	 * @param source
	 *            - 源文件
	 * 
	 * @param target
	 *            - 目标文件
	 * 
	 */
	public static void copyFile(File source, File target) {

		FileInputStream fi = null;
		FileOutputStream fo = null;

		FileChannel in = null;

		FileChannel out = null;

		try {
			fi = new FileInputStream(source);

			fo = new FileOutputStream(target);

			in = fi.getChannel();// 得到对应的文件通道

			out = fo.getChannel();// 得到对应的文件通道

			in.transferTo(0, in.size(), out);// 连接两个通道,并且从in通道读取,然后写入out通道

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fi.close();

				in.close();

				fo.close();

				out.close();

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

}



被用坏的DexClassLoader,关于DexClassLoader内存泄露的问题

标签:

原文地址:http://blog.csdn.net/windowsxp2014/article/details/44055899

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!