Cam*_*mer 5 java multithreading android garbage-collection
我一直在我们的Android应用程序中注意到,每次我们退出到主屏幕时,我们都会通过ByteArrayOutputStream的数量增加堆大小(泄漏).我能够管理的最好的是添加
this.mByteArrayOutputStream = null;
Run Code Online (Sandbox Code Playgroud)
在run()结束时防止堆大小不断增加.如果有人能够启发我,我将非常感激.我写了下面的例子来说明问题.
public class MainActivity extends Activity {
private Controller mController;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onStart() {
super.onStart();
this.mController = new Controller();
mController.connect();
}
@Override
protected void onStop() {
super.onStop();
mController.quit();
}
}
Run Code Online (Sandbox Code Playgroud)
public class Controller {
public volatile ReaderThread mThread;
public Controller() {
super();
}
public void connect() {
mThread = new ReaderThread("ReaderThread");
mThread.start();
}
public void quit() {
mThread.quit();
}
public static class ReaderThread extends Thread {
private volatile boolean isProcessing;
private ByteArrayOutputStream mByteArrayOutputStream;
public ReaderThread(String threadName) {
super(threadName);
}
@Override
public void run() {
this.isProcessing = true;
Log.d(getClass().getCanonicalName(), "START");
this.mByteArrayOutputStream = new ByteArrayOutputStream(2048000);
int i = 0;
while (isProcessing) {
Log.d(getClass().getCanonicalName(), "Iteration: " + i++);
mByteArrayOutputStream.write(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
try {
mByteArrayOutputStream.reset();
mByteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.d(getClass().getCanonicalName(), "STOP");
}
public void quit() {
this.isProcessing = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
线程对GC免疫,因为它们是垃圾收集根.因此,JVM可能会保留您ReaderThread的内存以及成员变量的分配,从而造成泄漏.
归零了ByteArrayOutputStream,因为你已经注意到,会使它的缓冲数据(但不包括ReaderThread本身)供GC.
编辑:
经过一番调查后,我们了解到Android调试器导致了泄漏:
VM保证调试器知道的任何对象在调试器断开连接之前不会被垃圾收集.在连接调试器时,这会导致对象随时间累积.例如,如果调试器看到正在运行的线程,则即使在线程终止后,关联的Thread对象也不会被垃圾回收.