Community
Participate
Working Groups
We compile using Eclipse JDK compliance 5.0 and have some classes which uses covariant feature in Java 1.5 f.e. for the clone()-Method. Our server components compiled using ant with target=1.5 using external jdk1.5._04 from sun. After deploying server-components to JBoss-Server and starting Client-Application from within Eclipse, we got incompatible serialversionuid exceptions from those classes which were using clone() as an covariant. After an decompilation and compare of classes from Eclipse and Sun jdk1.5._04 we found the difference in the compiler generated method: protected volatile Object clone() throws CloneNotSupportedException { return clone(); } which was marked as "protected" from Eclipse-compiler and was "public" from sun's jdk. So the serialversionuid can't be identical, i think the method must be public, is that a bug in Eclipse? Thanks in advance, Heiko
If the #clone() declaration is tagged as protected, then it must be generated as such. Also note that 'volatile' is not allowed for methods. Please provide a complete example reproducing the issue.
(In reply to comment #1) > If the #clone() declaration is tagged as protected, then it must be generated > as such. Also note that 'volatile' is not allowed for methods. > Please provide a complete example reproducing the issue. We've not implemented the code snippet (... protected volatile clone()) this was code we've decompiled from the generated class file. The implemented code looks like: @Override public SEPlatzierung clone() {...} and compiler adds covariant function: protected volatile Object clone() throws CloneNotSupportedException { return clone(); }
Here an simple example source: import java.io.Serializable; public class MyClass implements Serializable { private Long member; public MyClass(){ } @Override public MyClass clone(){ MyClass clone = new MyClass(); clone.setMember(new Long(member)); return clone(); } public Long getMember() { return member; } public void setMember(Long nValue) { member = nValue; } } After compilation in Eclipse the decompiled code from classfile: import java.io.Serializable; public class MyClass implements Serializable { public MyClass() { } public MyClass clone() { MyClass clone = new MyClass(); clone.setMember(new Long(member.longValue())); return clone(); } public Long getMember() { return member; } public void setMember(Long long1) { member = long1; } protected volatile Object clone() throws CloneNotSupportedException { return (Object)clone(); } private Long member; } The same sourcefile compiled with sun jdk1.5.0_04, here the decompiled code: import java.io.Serializable; public class MyClass implements Serializable { public MyClass() { } public MyClass clone() { MyClass myclass = new MyClass(); myclass.setMember(new Long(member.longValue())); return clone(); } public Long getMember() { return member; } public void setMember(Long long1) { member = long1; } public volatile Object clone() throws CloneNotSupportedException { return clone(); } private Long member; }
This method is not volatile. This is a bridge method. ACC_VOLATILE and ACC_BRIDGE are equal, so this is why it is shown as volatile. javac generates the bridge method as public and we generate it as protected. Kent, should we preserve the visibility of the method called by the bridge method? For the serial version id exception, you should define a serial version UID field for every serializable class. This is highly recommended. If you don't, then your serialized instances are compiler-dependent whatever the current behavior is right or not. There is no specification for some access emulation with regards to inner classes accesses and these access methods have a side-effect on the serial version uid.
We should indeed use the modifiers from the covariant method when generating a bridge method. class XSuper { Object foo() { return null; } protected Object bar() { return null; } } public class X extends XSuper { protected String foo() { return null; } public String bar() { return null; } }
Created attachment 44952 [details] Proposed patch
Released fix for 3.2.1 (TARGET_321) Released fix for 3.3M1 (HEAD) Added MethodVerifyTest#test090
Fixing this doesn't prevent you from defining the serialVersionUID field.
Verified for 3.3 M1 using build I20060807-2000.
Verified for 3.2.1 using build M20060908-1655