Could not read input channel file descriptors from parcel

目錄html

 

背景:java

卡死/黑屏log信息,緣由分析:linux

背景:
一個盤點掃描的APP,能夠離線在線操做,運行平臺爲PDA,客戶在使用過程當中反饋通過屢次掃描後會出現屏幕卡死/黑屏的狀況,可是PDA系統能夠正常使用,因而可知是個人APP致使的。客戶一次盤點會盤點近千個物品,也就是說會掃描近千次,掃描過程當中會有人聲提示音播放。收到了客戶的反饋後,拿了設備回來本身測,經過幾次合的連續掃描後,復現出了這個問題,每回合都是掃到237次就出現黑屏或者報錯。拿到了出現問題的log信息,可是一看logcat,很難肯定緣由,不是常規的代碼崩潰。如下看下我拿到的logcat信息android

卡死/黑屏log信息,緣由分析:
08-25 18:18:58.028 17875-17875/com.pda.wph E/Surface: dequeueBuffer failed (Invalid argument)
08-25 18:18:58.038 17875-17875/com.pda.wph E/ViewRootImpl: Could not lock surface
                                                           java.lang.IllegalArgumentException
                                                               at android.view.Surface.nativeLockCanvas(Native Method)
                                                               at android.view.Surface.lockCanvas(Surface.java:236)
                                                               at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2495)
                                                               at android.view.ViewRootImpl.draw(ViewRootImpl.java:2469)
                                                               at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2313)
                                                               at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1946)
                                                               at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1078)
                                                               at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5887)
                                                               at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
                                                               at android.view.Choreographer.doCallbacks(Choreographer.java:562)
                                                               at android.view.Choreographer.doFrame(Choreographer.java:532)
                                                               at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
                                                               at android.os.Handler.handleCallback(Handler.java:730)
                                                               at android.os.Handler.dispatchMessage(Handler.java:92)
                                                               at android.os.Looper.loop(Looper.java:137)
                                                               at android.app.ActivityThread.main(ActivityThread.java:5136)
                                                               at java.lang.reflect.Method.invokeNative(Native Method)
                                                               at java.lang.reflect.Method.invoke(Method.java:525)
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                               at dalvik.system.NativeStart.main(Native Method)
08-26 11:05:56.994 3741-3741/com.pda.wph E/InputChannel-JNI: Error 24 dup channel fd 1011.
08-26 11:05:57.004 3741-3741/com.pda.wph D/AndroidRuntime: Shutting down VM
08-26 11:05:57.004 3741-3741/com.pda.wph W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41b5a898)
08-26 11:05:57.004 3741-3741/com.pda.wph E/AndroidRuntime: FATAL EXCEPTION: main
                                                           java.lang.RuntimeException: Could not read input channel file descriptors from parcel.
                                                               at android.view.InputChannel.nativeReadFromParcel(Native Method)
                                                               at android.view.InputChannel.readFromParcel(InputChannel.java:148)
                                                               at android.view.IWindowSession$Stub$Proxy.addToDisplay(IWindowSession.java:690)
                                                               at android.view.ViewRootImpl.setView(ViewRootImpl.java:595)
                                                               at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:269)
                                                               at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
                                                               at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2857)
                                                               at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2269)
                                                               at android.app.ActivityThread.access$600(ActivityThread.java:144)
                                                               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1259)
                                                               at android.os.Handler.dispatchMessage(Handler.java:99)
                                                               at android.os.Looper.loop(Looper.java:137)
                                                               at android.app.ActivityThread.main(ActivityThread.java:5136)
                                                               at java.lang.reflect.Method.invokeNative(Native Method)
                                                               at java.lang.reflect.Method.invoke(Method.java:525)
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                               at dalvik.system.NativeStart.main(Native Method)
從上面的logcat日誌看 很難定位到問題發生的所在位置,因此也是耗費我大量的時間去網上搜尋答案。可是基本能夠排除掉的是第一部分的logcat緣由,個人APP中並無使用過surfaceview之類的控件,因此這個多是由其餘報錯影響致使。sql

這個時候,咱們就重點看第二個報錯信息Could not read input channel file descriptors from parcel數據庫

經過百度獲得了一些信息,可能致使出現這個報錯的幾個緣由app

RemoteView中添加的圖片太大了,超過40K會報這個異常(PS:排除,項目中沒有用到這個)
Intent傳遞的數據太大了超過1M也會報這個錯誤(PS:排除)
FileDescripter太多並且沒有關閉,looper太多沒有quit。
試試在AndroidManefest.xml中對當前Activity配置 (PS:項目中是強制豎屏)
configchange=「orientation|keyboardHidden」強制在Activity橫豎屏切換的時候不從新onCreate。
經過排除最終定位到了FileDescripter太多並且沒有關閉這個可疑的緣由,這個是什麼東西,我也不知道,只能再百度下。socket

能夠參考https://www.jianshu.com/p/e3830e7be8b2ide

能夠知道這個是句柄泄露照成的,一個進程擁有的最大句柄數通常是1024,一旦超過這個值,該進程就會出現句柄泄露,進而引起一些報錯狀況。工具

在linux中一個文件、一個串口、一個socket、一個線程均可以是一個文件,而一個文件會佔用一個句柄,linux中一個進程默認的句柄最大數值是1024,當超過這個數值,linux就會對當前的進程進行kill,而kill的對象能夠是任意對象,因此會形成各類異常緣由的崩潰。

這句資料參考至:http://www.cnblogs.com/dongweiq/p/9494033.html

好了 又要排除緣由了,

項目中沒有用到socket,排除;

項目中有sqlite數據庫備份還原操做,涉及到文件流操做,檢查後都有close,排除;

項目中沒有較多以及致使死循環的線程,排除;

排除後又陷入了迷茫當中,到底還有什麼會致使句柄泄露。

通過一段時間的分析後,關於文件的操做還有一個地方,播放人聲提示音,這裏播放提示音是使用SoundPool去實現的,在一次掃描中會播放兩個提示音,通過237次的掃描,也就是播放了484的提示音,SoundPool的load方法生成一個AssetFileDescriptor對象,多是沒有關閉進而致使句柄超過了1024泄露了,

參考至https://www.cnblogs.com/l2rf/p/6051169.html。

因此 針對SoundPool作下修改

如下是我本身修改後的工具類

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
 
 
/**
 *
 * 聲音播放類
 * Created by ZYB on 2017/7/21 0021.
 */
 
public class SoundPoolUtil {
 
 
    private static SoundPoolUtil soundPoolUtil;
    private static SoundPool soundPool;
    private static List<AssetFileDescriptor> FileDescriptors ;
 
    private SoundPoolUtil(){
 
        FileDescriptors = new ArrayList<>();
        soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100);
    }
 
    /**
     * 單例模式
     * @return
     */
    public static SoundPoolUtil newInstance()
    {
        if (soundPoolUtil == null) {
            soundPoolUtil = new SoundPoolUtil();
        }
        //清除soundpool資源,防止加載超過300次後沒聲音
        if (soundPool != null)
        {
            soundPool.release();
            soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100);
        }
        return soundPoolUtil;
 
    }
 
    /**
     * 播放聲音
     * @param resid 資源id
     * @param context   上下文對象
     */
    public  void playSoundPool(int resid, Context context)
    {
 
        try {
 
            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
            final int soundid = soundPool.load(afd,1);
            FileDescriptors.add(afd);
            soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
                @Override
                public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                    soundPool.play(soundid,1,1,0,0,1f);
                    Log.w("sound_play", soundid +"");
                    soundPool.unload(soundid);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
    //釋放FD資源,防止出現句柄超過1024泄露
    public void releaseFileDescriptor()
    {
        for (AssetFileDescriptor item : FileDescriptors)
        {
            try {
                //釋放FileDescriptor句柄
                item.close();
                item = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //清空列表
        FileDescriptors.clear();
    }
}
在使用SoundPool的Activity中的onDestory方法調用SoundPool.newInstance().releaseFileDescriptor()。

修改後通過一輪測試,連續掃描1000屢次也不會出現屏幕卡死/黑屏的問題了,問題解決。

多虧如下這些博客 我才解決了這個繁瑣的問題:

https://www.cnblogs.com/l2rf/p/6051169.html

http://www.cnblogs.com/dongweiq/p/9494033.html

https://www.jianshu.com/p/e3830e7be8b2

  ———————————————— 版權聲明:本文爲CSDN博主「乙-second」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/qq_33617079/article/details/82316606

相關文章
相關標籤/搜索