Bug 22445 - Compiler inconsistent with javac when code returns from inside a finally {} block
Summary: Compiler inconsistent with javac when code returns from inside a finally {} b...
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC other
: P3 normal (vote)
Target Milestone: 2.1 M2   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 46421 (view as bug list)
Depends on:
Blocks:
 
Reported: 2002-08-14 15:24 EDT by Andrew McCullough CLA
Modified: 2003-11-12 05:24 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew McCullough CLA 2002-08-14 15:24:33 EDT
When returning from within a finally{} block, the Eclipse compiler does not 
complain about an Exception that is not declared to be thrown, but javac does.  

Interestingly, the output of both programs (if I declare the throws) 
is "Shouldn't get here", so in that regard the compilers are consistent.  
Despite what the JLS might say about the issue (I am not a JLS expert), the 
bahavior of both compilers seems pretty wrong to me.  I don't like that the 
Exception gets "eaten" without an explicit catch.   I figured I should report 
the inconsistency.  

I of course defer to Phillip (or whoever :) ) to determine if it's really a 
compiler bug, since I have seen more than one report be explained by slightly 
different interpretations of vague JLS points.


The error reported by javac 1.3.1 is:

javac com\test\FinallyExceptionTest.java
com\test\FinallyExceptionTest.java:19: unreported exception 
java.lang.Exception; must be caught or d
eclared to be thrown
                        throw new Exception("Exception");
                        ^
1 error

Test case:

package com.test;

public class FinallyExceptionTest {

	public static void main(String[] arguments) {
		
		try {
			FinallyExceptionTest t = new FinallyExceptionTest();
			System.out.println("I shouldn't get here");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void doSomething() {
	
		try {
			
			throw new Exception("Exception");
			
		} finally {
			
			return;
		}	
	}
	
}
Comment 1 Andrew McCullough CLA 2002-08-14 15:27:53 EDT
Ooops, there should also be a call to t.doSomething() in there.  I was playing 
with the test case, but the other points remain the same.  

The correct test case is: 

package com.test;

public class FinallyExceptionTest {

	public static void main(String[] arguments) {
		
		try {
			FinallyExceptionTest t = new FinallyExceptionTest();
			t.doSomething();
			System.out.println("I shouldn't get here");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void doSomething() {
	
		try {
			
			throw new Exception("Exception");
			
		} finally {
			
			return;
		}	
	}
	
}
Comment 2 Philipe Mulet CLA 2002-08-16 07:50:49 EDT
Finally block have to be run during exception handling, and may cause abrupt 
termination of method. This is the language specified behavior. 

Technically, a finally block is not much different from a catch block which is 
ensured to be both on the exception and normal termination execution path.

In cases, this can become convenient to replace an exception with another one.
try {
  throw new A();
} finally {
  throw new B();
}

Returning finally blocks can easily become counter-intuitive:
try {
  return 1;
} finally {
  return 2;   // 2 will be returned
}

A good programming style is probably to avoid returning directly from whithin 
finally blocks.

Now for the compiler behavior, I would say our behavior is the proper one, in 
the sense it matches the runtime silent absorption of the exception. Will 
investigate some more.
Comment 3 Sanjay Madhavan CLA 2002-08-23 12:03:13 EDT
This behavior as I observed in JDK 1.4 also shows the problem.
/**
 * @author Sanjay Madhavan
 *
 * Test case to show a problem/feature? with exception handling and
 * method signatures when a finally block is specified.
 * This behavior is observed in Eclipse Version: 2.0 Build id: 200208201620
 * 
 * The Sun java compiler in JDK version "1.4.0_01" correctly flags the 
 * testExceptionWronglyCompiles method as incorrect.
 */
public class TestException {
	
	/*
	 * This method will compile. This is correct behavior
	 */
	public String testExceptionCorrect() throws Exception {
		throw new Exception();
	}

	/*
	 * This method will not compile. This is correct behavior
	 */
	public String testExceptionWillNotCompile() {
		if (true)
			throw new Exception();
		return "bogus";
	}
	/*
	 * This method will compile. This to me is INCORRECT behavior.
	 */
	public String testExceptionWronglyCompiles() {
		try {
			throw new Exception();
		} catch (Exception me) {
			throw me;

		} finally {
			// the return within the finally seems to confuse the 
compiler
			return "bogus";
		}
	}

	public static void main(String[] args) {
		TestException test = new TestException();
		System.out.println(
			"testExceptionWronglyCompiles returned: "
				+ test.testExceptionWronglyCompiles());
	}
}

Comment 4 Philipe Mulet CLA 2002-09-09 05:38:59 EDT
Sanjay - What makes you think our compiler is wrong ? When running the 
offending method, do you get any uncaught exception stack trace ? No, because 
the exception is never surfaced beyond the finally block. Javac doesn't notice 
it, we do.
Comment 5 Andrew McCullough CLA 2002-09-09 08:14:04 EDT
Just for the record (I can't speak for Sanjay), but I actually think Eclipse's 
interepretation is more "technically correct".  I just reported the bug to note 
the inconsistency as people get upset when something compiles in Eclipse and 
not with javac/jikes or vice versa.  

I am a little dissapointed this can happen at all according to the JLS.  
Throughout the language, Java is very careful to ensure exceptions are handled 
through some purposeful action (catch/throw), and in this case you 
can "accidentally" not handle an exception. 

Some well-meaning programmer on my project was trying to fix a "JTest" error 
(static code analysis) which complained there were too many return statements 
in the method.  Instead of improving the code, though, it caused a very subtle 
bug with the exceptional conditions.  Of course, once I noticed the return in 
the finally...

-Andrew

Comment 6 Philipe Mulet CLA 2002-09-30 05:27:33 EDT
Closing, behaving as expected.
Comment 7 Olivier Thomann CLA 2003-11-11 15:40:12 EST
*** Bug 46421 has been marked as a duplicate of this bug. ***
Comment 8 Philipe Mulet CLA 2003-11-12 05:24:20 EST
We added a warning to signal that the finally block is not completing normally.