JDK-6996415 : Override bridges causes compiler-generated code to end up with synthetic infinite loop
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: unknown
  • Submitted: 2010-11-01
  • Updated: 2013-03-09
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b118Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
But with b115 I am getting a stack overflow error.  This seems to be
because of problem with synthetic/bridge methods.

    at gnu.expr.FindTailCalls.visitExpression(FindTailCalls.java:22)
    at gnu.expr.ExpExpVisitor.visitExpression(ExpExpVisitor.java:8)
    at gnu.expr.FindTailCalls.visitExpression(FindTailCalls.java:33)
    at gnu.expr.FindTailCalls.visitExpression(FindTailCalls.java:22)

There are 3 classes:

abstract public class ExpVisitor<R,D> {
  protected R visitExpression (Expression exp, D d) { stuff; }
}
Java 6 or Java 7 both generate:
  Method#1 protected visitExpression (Expression,Object)Object [line 27-28]

abstract class ExpExpVisitor<D> extends ExpVisitor<Expression,D> {
}
Java6 generates no methods.
Java7 generates:
  Method#2 protected bridge synthetic visitExpression (Expression,Object)Expression [line 8]
    invokespecial ExpVisitor.visitExpression (Expression,Object)Object
  Method#3 protected bridge synthetic visitExpression (Expression,Object)Object [line 8]
    invokevirtual ExpExpVisitor.visitExpression (Expression,Object)Expression

class FindTails extends ExpExpVisitor<Expression> {
  protected Expression visitExpression (Expression exp, Expression returnContinuation) {
      return super.visitExpression(exp, exp);
  }
}
Java6 or Java7 both generate the natural:
  Method#3 protected visitExpression (Expression,Expression)Expression [line 33]
    invokespecial ExpExpVisitor.visitExpression (Expression,Object)Object
    [In Java6, calls natural method ExpVisitor.visitExpression directly, as intended.]
    [In Java 7, calls method#2 which calls method#5, which calls method#3.  Stack Overflow.]
Java6 or Java 7 both generate this synthetic:
  Method#4 protected bridge synthetic visitExpression (Expression,Object)Object [line 22]
    invokevirtual FindTailCalls.visitExpression(Expression,Expression)Expression
Java7 only generates this synthetic:
  Method#5 protected bridge synthetic visitExpression (Expression,Object)Expression [line 22]
    invokevirtual FindTailCalls.visitExpression (Expression,Expression)Expression

Look at Method#3.  In Java6, calls natural method ExpVisitor.visitExpression directly,
as intended.  In Java 7, method#3 calls method#2 which calls method#5, which calls method#3.
Stack Overflow.

Is this a known problem?  I'm guess one of you two know what changed and when.
Build 107 seems to be OK.

Comments
Once this issue is solved, it should be checked if the approach for JDK-6695379 can be applied also to override bridges.
09-03-2013

EVALUATION http://hg.openjdk.java.net/jdk7/build/langtools/rev/20659c8c917d
04-12-2010

SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/20659c8c917d
02-11-2010

EVALUATION I will temporarily disable 6337171 and investigate more. A follow up bug will keep track of progress on this issue.
02-11-2010

EVALUATION Consider this hierarchy: abstract class ExpVisitor<R,D> { protected R visitExpression (Expression exp, D d) { System.out.println(exp); return null; } } abstract class ExpExpVisitor<D> extends ExpVisitor<Expression,D> { } class FindTails extends ExpExpVisitor<Expression> { protected Expression visitExpression (Expression exp, Expression returnContinuation) { return super.visitExpression(exp, exp); } } The problem lies in the method descriptor associated with the 'super' call in FindTails - such descriptor is: ExpExpVisitor.visitExpression:(LExpression;Ljava/lang/Object;)Ljava/lang/Object; instead of ExpExpVisitor.visitExpression:(LExpression;Ljava/lang/Object;)LExpression; In other words, javac is generating the descriptor as if ExpExpVisitor *did not* override visitExpression (in fact, the overriding is synthetic, as such, the compiler generated method is not available during attribution). The result is bad, because, instead of calling the super method directly, the compiler ends up calling the super 'bridge' method, which, after a cast, calls (invokevirtual) again FindTails.visitExpression... resulting in a loop.
01-11-2010