Auf der Suche nach einem Speicherleck in meiner App habe ich ein Verhalten verfolgt, das ich nicht verstehen kann. Ich reserviere einen großen Speicherblock, aber es wird keine Speicherbereinigung erhalten, was zu einem OOM führt, außer wenn ich den Verweis explizit in onDestroy auf Null setze.Großer Speicherbrocken nicht Müll gesammelt
In diesem Beispiel habe ich zwei fast identische Aktivitäten, die zwischen den anderen wechseln. Beide haben einen einzigen Knopf. Beim Drücken der Schaltfläche MainActivity startet OOMActivity und OOMActivity kehrt durch Aufruf von finish() zurück. Nach einigen Drücken der Tasten löst Android eine OOMException aus.
Wenn ich die onDestroy zu OOMActivity hinzufügen und explizite null den Verweis auf den Speicher Chunk, kann ich in dem Protokoll sehen, dass der Speicher ordnungsgemäß freigegeben ist.
Warum wird der Speicher nicht automatisch ohne Nullung freigegeben?
MainActivity:
package com.example.oom;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private int buttonId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.gc();
Button OOMButton = new Button(this);
OOMButton.setText("OOM");
buttonId = OOMButton.getId();
setContentView(OOMButton);
OOMButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == buttonId) {
Intent leakIntent = new Intent(this, OOMActivity.class);
startActivity(leakIntent);
}
}
}
OOMActivity:
public class OOMActivity extends Activity implements OnClickListener {
private static final int WASTE_SIZE = 20000000;
private byte[] waste;
private int buttonId;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button BackButton = new Button(this);
BackButton.setText("Back");
buttonId = BackButton.getId();
setContentView(BackButton);
BackButton.setOnClickListener(this);
waste = new byte[WASTE_SIZE];
}
public void onClick(View view) {
if (view.getId() == buttonId) {
finish();
}
}
}
gutes Beispiel, gute Frage! – WarrenFaith
Bitte lesen Sie diesen Chat. Wir haben es [hier besprochen] (http://chat.stackoverflow.com/transcript/message/10084186#10084186) – Reno
Sie testen das wahrscheinlich auf einem Pre-Waben-Gerät. Der Müllsammler auf Post-Waben wird aggressiv genug sein, um das "Abfall" -Objekt freizugeben. Getestet an 4.1.2, 4.2.2, 2.3.5, 2.3.7. Durch Aufruf von System.gc() vor "vergeuden = neues Byte [WASTE_SIZE]" wird das Problem auf Pre-Waben-Geräten vermieden. – pellucide