应用程序强制关闭 - OutOfMemoryError

Posted

技术标签:

【中文标题】应用程序强制关闭 - OutOfMemoryError【英文标题】:App force closing - OutOfMemoryError 【发布时间】:2014-12-29 19:14:57 【问题描述】:

我一直在尝试测量麦克风在设备后台运行时使用的电池电量,因此我编写了一个小应用程序来测试它。

在我的手机外部存储上,我使用该应用创建了一个 600mb 的 PCM 文件录音,以及第二个 100mb 的录音。

当我运行应用程序并尝试播放 100mb 文件时,它运行良好。 但是,当我尝试播放较大的 600mb 时,它会在代码行上崩溃:

InputStream is = new FileInputStream(file);

logcat 给出了错误:

`11-03 16:31:03.654  16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc sticky concurrent mark sweep GC freed 6307(421KB) AllocSpace objects, 1(12KB) LOS objects, 33% free, 15MB/23MB, paused 678us total 14.444ms
11-03 16:31:03.663  16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc partial concurrent mark sweep GC freed 213(22KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 15MB/26MB, paused 659us total 7.132ms
11-03 16:31:03.679  16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc concurrent mark sweep GC freed 15(12KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 15MB/26MB, paused 830us total 14.191ms
11-03 16:31:03.681  16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Forcing collection of SoftReferences for 641MB allocation
11-03 16:31:03.695  16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 39% free, 15MB/26MB, paused 645us total 13.989ms
11-03 16:31:03.700  16916-16916/com.bacon.corey.audiotimeshift E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 672164876 byte allocation with 11094652 free bytes and 176MB until OOM"
11-03 16:31:03.703  16916-16916/com.bacon.corey.audiotimeshift D/androidRuntime﹕ Shutting down VM
11-03 16:31:03.713  16916-16916/com.bacon.corey.audiotimeshift E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.bacon.corey.audiotimeshift, PID: 16916
    java.lang.IllegalStateException: Could not execute method of the activity
            at android.view.View$1.onClick(View.java:4007)
            at android.view.View.performClick(View.java:4756)
            at android.view.View$PerformClick.run(View.java:19749)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at android.view.View$1.onClick(View.java:4002)
            at android.view.View.performClick(View.java:4756)
            at android.view.View$PerformClick.run(View.java:19749)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.OutOfMemoryError: Failed to allocate a 672164876 byte allocation with 11094652 free bytes and 176MB until OOM
            at com.bacon.corey.audiotimeshift.MainActivity.play(MainActivity.java:87)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at android.view.View$1.onClick(View.java:4002)
            at android.view.View.performClick(View.java:4756)
            at android.view.View$PerformClick.run(View.java:19749)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)`

我没有用 android 做很多文件 IO 的东西,所以我不确定我在这里做错了什么。 如果有人不介意指出我哪里出错了,我将非常感激。

类的代码如下。

提前致谢 科里:)

        public void play(View view) 
        Toast.makeText(this, "play", Toast.LENGTH_SHORT).show();

// Get the file we want to playback.
        File file = new File(Environment.getExternalStorageDirectory() + File.separator + "ACS.pcm");
// Get the length of the audio stored in the file (16 bit so 2 bytes per short)
// and create a short array to store the recorded audio.
        int musicLength = (int)(file.length()/2);
        short[] music = new short[musicLength];


        try 
// Create a DataInputStream to read the audio data back from the saved file.
            InputStream is = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);

// Read the file into the music array.
            int i = 0;
            while (dis.available() > 0) 
                music[musicLength-1-i] = dis.readShort();
                i++;
            


// Close the input streams.
            dis.close();


// Create a new AudioTrack object using the same parameters as the AudioRecord
// object used to create the file.
            AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                    44100,
                    AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    musicLength,
                    AudioTrack.MODE_STREAM);
// Start playback
            audioTrack.play();

// Write the music buffer to the AudioTrack object
            audioTrack.write(music, 0, musicLength);


         catch (Throwable t) 
            Log.e("AudioTrack","Playback Failed");
        
    

【问题讨论】:

【参考方案1】:

看起来您在尝试对其进行任何操作之前将整个音频文件加载到内存中。这是一种不好的方法,因为您的文件看起来像是 672164876 字节 (641MB),我猜这比您在可能最多具有 1-总共 2GB 的 RAM 可在所有正在运行的应用程序(加上 Android 操作系统本身)之间共享。

虽然您尝试在如此低的级别执行此操作(读入所有字节并将它们直接写入将播放它们的东西),但我建议您研究内置的 Android 媒体 API,例如MediaPlayer 解释了 in this other *** post 或一些更高级别的库,其中任何一个都应该处理将文件流式传输到内存并播放它的所有细节,因此您不必这样做。

【讨论】:

以上是关于应用程序强制关闭 - OutOfMemoryError的主要内容,如果未能解决你的问题,请参考以下文章

强制关闭一个正在运行的程序应该怎么做?

如何强制系统关闭底层套接字

Macbook怎么强制关闭后台程序?Macbook强制关闭后台程序的方法

如何处理离子应用程序中的强制关闭事件?

怎样使用ADB命令强制关闭蓝牙!

如何强制关闭程序