У меня были сбои приложений из-за нехватки памяти (в программе, а не в программисте). MAT показывает, что копии моей Activity иногда сохранялись при поворотах экрана, и единственным объектом, поддерживающим поддельные копии, был объект TextToSpeech каждого экземпляра. Я могу продублировать это поведение, используя этот фрагмент:
public class MainActivity extends Activity {
TextToSpeech mTts;
char[] mBigChunk = new char[1000000]; // not used; just makes MainActivity instances easier to see in MAT
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onStart() {
super.onStart();
if (mTts==null) // shouldn't be necessary and doesn't make any difference
mTts = new TextToSpeech(this, null); // commenting this out fixes the leak
}
@Override
public void onStop() {
super.onStop();
if (mTts != null) {
mTts.shutdown();
mTts = null; // shouldn't be necessary and doesn't make any difference
}
}
}
После 30 изменений ориентации MAT перечисляет от одного до восьми экземпляров net.catplace.tts_leak.MainActivity, а также несколько экземпляров различных объектов TTS; например:
Class Name | Shallow Heap | Retained Heap | Percentage
------------------------------------------------------------------------------------------------------------------
android.speech.* | | |
android.speech.tts.TextToSpeech$Connection$1 @ 0x42de94c8 Native Stack| 24 | 2,052,664 | 11.85%
android.speech.tts.TextToSpeech$Connection$1 @ 0x431dd500 Native Stack| 24 | 2,052,664 | 11.85%
android.speech.tts.TextToSpeech$Connection$1 @ 0x435cc438 Native Stack| 24 | 552 | 0.00%
android.speech.tts.TextToSpeech$Connection @ 0x441b3698 | 32 | 528 | 0.00%
android.speech.tts.TextToSpeech @ 0x43fb3c00 | 64 | 496 | 0.00%
android.speech.tts.TextToSpeech$Connection @ 0x43fb4420 | 32 | 48 | 0.00%
android.speech.tts.TextToSpeech$Connection$1 @ 0x43fb4440 Native Stack| 24 | 24 | 0.00%
android.speech.tts.TextToSpeech$Connection$1 @ 0x441b36b8 Native Stack| 24 | 24 | 0.00%
Total: 8 entries (13,079 filtered) | | |
------------------------------------------------------------------------------------------------------------------
MAT указывает, что поддельные копии MainActivity сохраняются TTS:
Class Name | Shallow Heap | Retained Heap
---------------------------------------------------------------------------------------------------------------------
| |
net.catplace.tts_leak.MainActivity @ 0x437c6068 | 200 | 2,001,352
'- mContext android.speech.tts.TextToSpeech @ 0x431de6d8 | 64 | 496
'- this$0 android.speech.tts.TextToSpeech$Connection @ 0x441b3698 | 32 | 528
'- this$1 android.speech.tts.TextToSpeech$Connection$1 @ 0x441b36b8 Native Stack| 24 | 24
---------------------------------------------------------------------------------------------------------------------
Я получаю такое поведение на ряде реальных устройств и AVD. Приведенные выше результаты получены на Nexus 7.
Я пробовал разные движки TTS, используя разные события для создания и уничтожения mTts и т. д.
Моя гипотеза заключается в том, что TextToSpeech не всегда обнуляет свою ссылку на контекст, который ее создал, что приводит к утечке копий контекста (Activity). Но я новичок в этом; есть что-то, что я делаю неправильно?
getApplicationContext()
, а неthis
(Activity), проблема, похоже, не возникает. Это имеет смысл, поскольку приложение не уничтожается при изменении ориентации. Хотя, мне кажется, в этом нет необходимости. - person Peter McLennan   schedule 31.10.2013