Q: ObjectInputStream readObject calls cause stackOverFlowError Okay, my code is huge but I will simplify it so you can get it fast. So generaly my code algorithm is: 

1. Reading bitmap from SD card (which is a face image).
2. Reading one object from SD card for each read photo and deserializing it (object contains coordinates of face regions such as eyes, nose, mouth etc).
3. Processing image and getting some data from it.
4. Writting data to .txt files on SD card.
There is a method that is using a recurency (presented below). I enter list which contains photos paths as argument. Then for each photo I deserialize object from SD card. After success call - I enter dezerialized object to processPhoto method with other parameters. After processPhoto() finish processing it calls interface onPhotoProcessFinished(). Interface increments "imageProcessed" and invokes processNextImageIfPossible again. Process repeats until all photos are processed. It works, but after like 50 iterations I get error. Do you have idea how I could fix this?
private void processNextImageIfPossible(List<String> photosToProcess) {
    if (imageProcessed < imageToProcess) {

          try{
               File photoDataFile = new File(photosToProcess.get(imageProcessed).replace("jpg", "data").substring(6));   
               ObjectInputStream ois = new ObjectInputStream(new FileInputStream(photoDataFile));
               FaceData faceData  = (FaceData) ois.readObject(); // ERROR HAPPENS HERE     
               ois.close();


                if (photosToProcess.get(imageProcessed).contains(EMOTION_NEUTRAL)) {
                    neutralImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_NEUTRAL);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_HAPPINESS)) {
                    happinessImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_HAPPINESS);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_SADNESS)) {
                    sadnessImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_SADNESS);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_ANGER)) {
                    angerImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_ANGER);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_SUPRISE)) {
                    supriseImages++; 
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_SUPRISE);
                }
           }catch(Exception ex){
               Toast.makeText(NeuralNetworkActivity.this, getString(R.string.process_file_read_error), Toast.LENGTH_LONG).show();
               ex.printStackTrace();
           } 

    } else {
        //createAndTrainNeuralNetwork();
    }
}

@Override
public void onPhotoProcessFinished() {
    imageProcessed++;
    processNextImageIfPossible(photosToProcessList);    
}

Error log:
06-27 02:46:31.856: E/AndroidRuntime(11552): FATAL EXCEPTION: main
06-27 02:46:31.856: E/AndroidRuntime(11552): Process: org.opencv.samples.facedetect, PID: 11552
06-27 02:46:31.856: E/AndroidRuntime(11552): java.lang.StackOverflowError
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.lang.Thread.currentThread(Thread.java:470)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.lang.ThreadLocal.get(ThreadLocal.java:53)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at dalvik.system.BlockGuard.getThreadPolicy(BlockGuard.java:139)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at libcore.io.BlockGuardOs.read(BlockGuardOs.java:148)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at libcore.io.IoBridge.read(IoBridge.java:425)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.FileInputStream.read(FileInputStream.java:179)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at libcore.io.Streams.readFully(Streams.java:81)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.DataInputStream.readFully(DataInputStream.java:99)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.DataInputStream.decodeUTF(DataInputStream.java:178)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.DataInputStream.decodeUTF(DataInputStream.java:173)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.DataInputStream.readUTF(DataInputStream.java:169)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readFieldDescriptors(ObjectInputStream.java:895)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:1719)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1631)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:658)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1781)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:762)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1981)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1938)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:162)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:177)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.onPhotoProcessFinished(NeuralNetworkActivity.java:195)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processImage(NeuralNetworkActivity.java:504)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralNetworkActivity.processNextImageIfPossible(NeuralNetworkActivity.java:171)
06-27 02:46:31.856: E/AndroidRuntime(11552):    at org.opencv.samples.facedetect.ui.activity.NeuralN


A: Looks like an infinite recursive loop between processImafge, onPhotoProcessFinished, and processNextImageIfPossible.  You need to prevent onPhotoProcessFinished from calling processNextImageIfPossible.  Doing so on a Handler rather than as a direct function call ought to be sufficient.

A: Well idea with handler should work because it uses other thread. That was good hint. I managed to fix it with usage of AsyncTask. I don't understand memory processes too well but there was too much going on on UI thread. Code below works:
private void processNextImageIfPossible(final List<String> photosToProcess) {
    if (imageProcessed < imageToProcess) {

        final String filePath = photosToProcess.get(imageProcessed).replace("jpg", "data").substring(6);

        new AsyncTask<Void, Void, FaceData>() {

            @Override
            protected FaceData doInBackground(Void... params) {
                 try{
                       File photoDataFile = new File(filePath);  
                       ObjectInputStream ois = new ObjectInputStream(new FileInputStream(photoDataFile));
                       FaceData faceData  = (FaceData) ois.readObject();       
                       ois.close();

                       return faceData;
                 }catch(Exception ex){

                       Toast.makeText(NeuralNetworkActivity.this, getString(R.string.camera_load_error), Toast.LENGTH_LONG).show();
                       ex.printStackTrace();
                       return null;
                 } 
            }

            @Override
            protected void onPostExecute(FaceData faceData) {

                if (photosToProcess.get(imageProcessed).contains(EMOTION_NEUTRAL)) {
                    neutralImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_NEUTRAL);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_HAPPINESS)) {
                    happinessImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_HAPPINESS);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_SADNESS)) {
                    sadnessImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_SADNESS);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_ANGER)) {
                    angerImages++;
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_ANGER);
                } else if (photosToProcess.get(imageProcessed).contains(EMOTION_SUPRISE)) {
                    supriseImages++; 
                    processImage(Uri.parse(photosToProcess.get(imageProcessed)), faceData, EMOTION_SUPRISE);
                }

                super.onPostExecute(faceData);
            }   
        }.execute();

    } else {
        //createAndTrainNeuralNetwork();
    }
}

