JDK-8029563 : Method.getAnnotations() changed its return value in JDK 8.
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux
  • Submitted: 2013-12-04
  • Updated: 2015-06-16
  • Resolved: 2013-12-06
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 1.8.0-ea-b117)

ADDITIONAL OS VERSION INFORMATION :
My test is running on the public CI-Server Travis: https://travis-ci.org/stefanbirkner/oraclejdk8-method-getannotations-bug/jobs/14898742

A DESCRIPTION OF THE PROBLEM :
I have two classes Super and Sub in the package foobar.

class Super {
  @org.junit.Test
  public void methodOfSuper() {
  }
}

public class Sub extends Super {
}

It is important that the Super has package visibility. The call Sub.class.getMethod("methodOfSuper").getAnnotations() returns different values in JDK 7 and JDK 8. On JDK 7 it has no annotations while on JDK 8 it has one annotation (@Test).

(This bug has been found to be the cause of a JUnit bug: https://github.com/junit-team/junit /issues/749 )

REGRESSION.  Last worked in version 7u45

ADDITIONAL REGRESSION INFORMATION:
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Clone the project https://github.com/stefanbirkner/oraclejdk8-method-getannotations-bug and run mvn test.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
mvn test should be successful.
ACTUAL -
mvn test fails.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
https://github.com/stefanbirkner/oraclejdk8-method-getannotations-bug
---------- END SOURCE ----------
Comments
See also this mail thread: http://mail.openjdk.java.net/pipermail/compiler-dev/2013-November/008147.html
06-12-2013

When compiling Sub you get an extra method, an "access bridge", that lets clients outside the package call the methodOnSuper() method that is a meber of Sub: ----- $ javap -p -v foobar/Sub.class public class foobar.Sub extends foobar.Super public foobar.Sub(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method foobar/Super."<init>":()V 4: return LineNumberTable: line 3: 0 public void methodOfSuper(); descriptor: ()V flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #2 // Method foobar/Super.methodOfSuper:()V 4: return LineNumberTable: line 3: 0 ----- In 8 we started copying annotations to bridges (see JDK-6695379) so the annotation is actually present in the class file when compiling with 8: ----- $ javap -p -v foobar/Sub.class public class foobar.Sub extends foobar.Super SourceFile: "Sub.java" minor version: 0 major version: 52 #11 = Utf8 Ljava/lang/Deprecated; #12 = Utf8 SourceFile #13 = Utf8 Sub.java #14 = NameAndType #5:#6 // "<init>":()V #15 = NameAndType #9:#6 // methodOfSuper:()V #16 = Utf8 foobar/Sub #17 = Utf8 foobar/Super { public foobar.Sub(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method foobar/Super."<init>":()V 4: return LineNumberTable: line 3: 0 public void methodOfSuper(); descriptor: ()V flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #2 // Method foobar/Super.methodOfSuper:()V 4: return LineNumberTable: line 3: 0 RuntimeVisibleAnnotations: 0: #11() ---- Note that I changed the annotation to "Deprecated". This is working as intended.
06-12-2013

I suspect this is related to the javac change which copies annotations to bridge methods, JDK-6695379.
05-12-2013