2

I have troubles understanding this;

public static void main(String[] args){
    int nulberOfTests = 10;
    for( int i=0 ; i < numberOfTest ; i++){
        try{
            File file = getRandomFile(directory);
            foo(file);
        }catch(IOException){
            System.out.println("Failed to split the file: " + file.getName());
        }
    }
}

foo(File file) throws IOException{
    System.out.println("Starting foo with " +file.getName());
    List<String> blockFiles = split(file);  //this throws IOException.
    for(int i =0 ; i< blockFiles.size(); i++){
        try{
            bar(blockFiles.get(i)); //this throws some exceptions
        }catch (Exception e){
            System.err.println("Failed bar on " + blockFiles.get(i));
            e.printStackTrace();
            //Handle the exception
        }finally{
            //clean up
        }
    }
//continue with the function
}

In my mind it is so: i launch a foo; it try to plit the file; if it fails, it throws IOException and i just write it and continue with another foo(file) (with another file). This is working as expected.

If it works, then i have a list of blockFiles names, and i go in the other loop to run bar on each blockFiles. If a bar fails, then i handle the exception, clean up the stuff, and continue the loop with the next blockfile.

However, what happens is: it start to handle the exception and at the same time, start another foo with another file. I can have an output like this:

Starting foo with file7
Failed bar on file7.block3
Starting foo with file12
Java.lang.NullPointerException
....

So the printStackTrace happens AFTER the next foo start. And i don't understand this. It should just continue with the loop of bar functions and with the rest of foo, before going back to main loop and starting another foo.

Can someone explain me this weird behavior? And maybe tell me what to change so that everything in the catch run before another foo start?

PS: I know this is not "Minimal Complete and Verifiable", but there is just too much stuff in this to makes it complete and verifiable, and it would have been really harder to understand. I hope what's here will be enough.

Nicholas K
  • 15,148
  • 7
  • 31
  • 57
Ablia
  • 317
  • 1
  • 3
  • 14
  • The program is probably working in the correct sequence. The behavior you're seeing must be linked only to the flushing of system.out's buffers. Take a look at this: https://stackoverflow.com/questions/19183955/why-we-use-system-out-flush/19184077 – ernest_k Sep 08 '18 at 12:13
  • I can't see any obvious problem. Can you try debugging your code to see exactly what is throwing that exception? Or, can you include the stack trace? Also, what is the `split()` method doing here? – Tim Biegeleisen Sep 08 '18 at 12:14
  • i know what is throwing the exception, but that's not my problem here. I have to make sure the programm continue to run even if an exception is throwed. That's why i need the catch to do all his stuff before going further with another foo function. I'll ad details to my post. – Ablia Sep 08 '18 at 13:21
  • Or maybe not. I guess @ernest_k and Stephen are right: it is going further with the catch, but not printing in the right order. – Ablia Sep 08 '18 at 13:27

2 Answers2

2

Your question is very hard to understand, and the code is clearly not real, but I think you are asking why the messages are being displayed in an unexpected order.

One possible answer is this:

System.out.println("Failed to split the file: " + file.getName());
System.out.println("Starting foo with " +file.getName());
System.err.println("Failed bar on " + blockFiles.get(i));
e.printStackTrace();

Did you notice that some of those print to System.out, and others to System.err?

Those are two distinct streams. Even if they are redirected to the same place, within Java the two streams are buffered separately and have different "autoflush" characteristics. This means that the output is liable to be interspersed in unexpected ways. For example:

public static void (String[] args) {
     System.out.println("Hi");
     System.err.println("Mom");
}

Might output:

Hi
Mom

or

Mom
Hi

If you need your error messages or stacktraces to appear in the order your code writes them, just use ONE stream for the messages.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Oh, ok. I thought that the programm was running in an unexpected order (starting new foo before finishing catch), but this explanation makes much more sens. Thanks! – Ablia Sep 08 '18 at 13:29
0

The accepted answer is incorrect or at least ambiguous.

If you substitute the System.err with a System.out the order of the two println will be the same: the error and then the start of the new file.

What is out of order is the stack trace.

The reason is the same. The method java.lang.Throwable.printStackTrace() writes on the System.err.

If you want the order that you expect, print the stack trace and the messages in the same stream.

To print the stack trace on the System.out, use:

e.printStackTrace(System.out);

java.lang.Throwable.printStackTrace()

Marco Altieri
  • 3,726
  • 2
  • 33
  • 47