Community
Participate
Working Groups
Using covariant return type feature through ITD causes ajc to produce bad code (which then causes reflection based usages, Hibernate in my case, to produce serious errors). Here is a minimal program to reproduce the error: // Entity.java import java.io.Serializable; public interface Entity { public Long getId(); } class AnEntity implements Entity { public Long getId() { return null; } } aspect ManageEntity { declare parents: Entity implements EntityWithId; interface EntityWithId { public Serializable getId(); } } > ajc -v AspectJ Compiler DEVELOPMENT built on Friday Nov 25, 2005 at 18:17:07 GMT > ajc -1.5 Entity.java > javap AnEntity Compiled from "Entity.java" class AnEntity extends java.lang.Object implements Entity{ AnEntity(); public java.lang.Long getId(); public java.io.Serializable getId(); } Now there are two getId() methods with only return type difference, which is illegal in Java.
I'll take a look tomorrow.
Here is a pure java program: import java.io.Serializable; public interface Entity2 { public Long getId(); } class AnEntity implements Entity2,EntityWithId { public Long getId() { return null; } } interface EntityWithId { public Serializable getId(); } After compilation, if I 'javap AnEntity': class AnEntity extends java.lang.Object implements Entity2,EntityWithId{ AnEntity(); public java.lang.Long getId(); public java.io.Serializable getId(); } You can have two methods that differ purely in return type - one has to be a bridge method that forwards to the other, here is implementation of the 'Serializable getId()' method: public java.io.Serializable getId(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokevirtual #2; //Method getId:()Ljava/lang/Long; 4: areturn LineNumberTable: line 7: 0 It just calls the getId() returning a Long. AspectJ is doing the same thing. However ... there is *possibly* a bug that has concerned me for a while to do with how we tag methods as bridge methods. Either: we aren't tagging them correctly for hibernate or hibernate doesn't understand bridge methods. Ramnivas, can you try hibernate against a pure java case that results in bridge methods like the one above?
Ramnivas, have you had a chance to try hibernate on the pure Java version of this that includes bridge methods? We're in danger of missing fixing this for RC1 if there is a real problem lurking...
Good news! It is Hibernate's problem. I tried the same setup in plain Java and got identical failure. public interface SerializableEntity { public Serializable getId(); } And then public class Entity implements SerializableEntity, Serializable { private Long _id; public Long getId() { return _id; } @SuppressWarnings("unused") private void setId(Long id) { _id = id; } } Therefore, marking this bug as "INVALID". Thanks Andy for working on this. I will do more investigation and report to Hibernate.