8

In this java code,

import java.io.IOException;

public class Copy
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         System.err.println("usage: java Copy srcFile dstFile");
         return;
      }

      int fileHandleSrc = 0;
      int fileHandleDst = 1;
      try
      {
         fileHandleSrc = open(args[0]);
         fileHandleDst = create(args[1]);
         copy(fileHandleSrc, fileHandleDst);
      }
      catch (IOException ioe)
      {
         System.err.println("I/O error: " + ioe.getMessage());
         return;
      }
      finally
      {
         close(fileHandleSrc);
         close(fileHandleDst);
      }
   }

   static int open(String filename)
   {
      return 1; // Assume that filename is mapped to integer.
   }

   static int create(String filename)
   {
      return 2; // Assume that filename is mapped to integer.
   }

   static void close(int fileHandle)
   {
      System.out.println("closing file: " + fileHandle);
   }

   static void copy(int fileHandleSrc, int fileHandleDst) throws IOException
   {
      System.out.println("copying file " + fileHandleSrc + " to file " +
                         fileHandleDst);
      if (Math.random() < 0.5)
         throw new IOException("unable to copy file");

      System.out.println("After exception");
   }
}

the output that I expect is

copying file 1 to file 2
I/O error: unable to copy file
closing file: 1
closing file: 2

However sometimes I get this expected output and at other times I get the following output:

copying file 1 to file 2
closing file: 1
closing file: 2
I/O error: unable to copy file  

and sometimes even this output:

I/O error: unable to copy file
copying file 1 to file 2
closing file: 1
closing file: 2

and whether I get the first, second or third output seems to happen randomly during every execution. I found THIS POST that apparently talks about the same problem, but I still don't understand why I sometimes get output 1, 2 or 3. If I understand this code correctly then output 1 should be what I get every time (the exception occurs). How do I ensure that I get output 1 consistently, or be able to tell when I will be getting output 1 or when I will be getting output 2 or 3?

Community
  • 1
  • 1
user13267
  • 6,871
  • 28
  • 80
  • 138
  • possible duplicate of [Random printing order for System.out & System.err calls](http://stackoverflow.com/questions/12594537/random-printing-order-for-system-out-system-err-calls) – user93353 Jul 26 '13 at 06:22

5 Answers5

19

The issue is that you are writing some output to System.out and some to System.err. These are independent streams, with independent buffering. The timing of when they are flushed is, as far as I know, not specified.

The short of it is that when writing to different streams, you cannot use the order in which the output shows up to determine the order in which the calls to println() occurred. Note that the output to System.out always appears in the expected order.

As far as order of execution, the body of the try is executed first. If it throws an exception, the body of the appropriate catch clause is then executed. The finally block is always executed last.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • but theoretically, the order should be the one as shown in output 1 shouldn't it? – user13267 Jul 26 '13 at 06:20
  • 1
    @user13267 - Yes. The order of execution is specified and it corresponds to the order you expected for the output. Make everything go to a single stream (e.g., `System.out`) and you should see your expected order every time. Alternatively, call `flush()` on each output stream immediately after each time you write to it. That should also fix the order in which the output appears on the console. – Ted Hopp Jul 26 '13 at 06:20
  • I tried `System.out.flush()` and `System.err.flush()` each time they were called, but still the output order remains the same. – user13267 Jul 26 '13 at 06:33
  • However, always writing everything to `System.out` seems to show it in the correct order everytime – user13267 Jul 26 '13 at 06:35
  • @user13267 - When you call `flush()`, what do you mean "the output order remains the same"? Do you mean that you still occasionally get unexpected output order? Or do you mean that the output is always in the same order (never changing)? – Ted Hopp Jul 26 '13 at 06:37
  • I meant I get the unexpected outputs, either output 2 or output 3, as posted in my question; and which one I get seems to happen randomly – user13267 Jul 26 '13 at 06:38
  • @user13267 - if you're sure that you are always flushing the correct stream (the one to which you just wrote), I'm a bit surprised. But since the behavior is not specified and probably implementation-dependent, it's only a mild surprise. – Ted Hopp Jul 26 '13 at 06:49
4

First execute Try block if it is success finally will execute, if try block fail then catch will execute and finally execute. What ever happen finally block will execute.

But

If you call System.exit(0) finally block not executed

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • What ever happen finally block will execute i wont agree to that what if System.exit() is called ? – Dungeon Hunter Jul 26 '13 at 06:23
  • @Sunny yes you are correct, but i am talking about this case only. If you call System.exit(0) in the try. Or make something that makes the JVM quit or hang (like a deadlock). Otherwise - no. – Ruchira Gayan Ranaweera Jul 26 '13 at 06:28
2

The thing with exception handling using try catch block is that the control will go inside try if any exception it will get inside catch block. But the control will go to final block every time it executs.

Maclane
  • 67
  • 1
  • 7
1

You are writing your error message to both stdout and stderr. They have different buffers, so there is no guarantee that the output you see will be in the same order as you created it, between the two output streams.

Since I can see no errors in your code (although the superfluous return; in your catch segment stuck in my craw a little bit), let me suggest that you write all of your messages to stderr, and see if the message order is a little more in line with what you were expecting.

Curt
  • 5,518
  • 1
  • 21
  • 35
1

You have one glitch in your example which I would remove. You are writing to both System.out and System.err and expection your console to synchronize both streams correctly. To remove side effects I would just use one stream here.

Matthias
  • 3,582
  • 2
  • 30
  • 41