TextToSpeech and memory leak

左心房为你撑大大i 提交于 2019-12-07 06:07:31

问题


I've been having app crashes due to an out-of-memory condition (in the program, not the programmer). MAT shows that copies of my Activity were sometimes being retained across screen rotations, and the only object keeping the bogus copies alive was each instance's TextToSpeech object. I can duplicate this behaviour using this snippet:

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
        }
    }
}

After 30 orientation changes, MAT lists between one and eight instances of net.catplace.tts_leak.MainActivity, and also multiple instance of various TTS objects; eg:

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 indicates that the bogus copies of MainActivity are being retained by 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
---------------------------------------------------------------------------------------------------------------------

I get this behavour across a range of real devices and AVDs. The above results are from a Nexus 7.

I've tried different TTS engines, using different events to create and destroy mTts, etc.

My hypothesis is that TextToSpeech doesn't always null its reference to the context that created it, resulting in leaked copies of the context (Activity). But I'm new at this; is there something I'm doing wrong?


回答1:


Taking a look at the source code of TextToSpeech here, you'll notice that it actually binds a service to the context passed and the shutdown method actually unbinds it. Now rest ahead is guess, since Service has its own life cycle,the TextToSpeech might be holding back the context.If you did some research keeping this in mind that you're actually running a service,you might crack the question.

Now I'm not also sure what this might imply but I am open for any new findings from your side. Given that TextToSpeech is a service you might want to pass it the application context, since the service would still be running when activity gets destroyed.

Also for further reading ______________




回答2:


If not implemtned android:configChanges="orientation" then you can override onDestory method:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (ttsEngine != null) {
        ttsEngine.stop();
        ttsEngine.shutdown();
        Log.d(TAG, "TTS destroyed");
    }
}


来源:https://stackoverflow.com/questions/19653223/texttospeech-and-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!