FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
When an array for which a getter/setter exists is made public, it is completely ignored by XMLEncoder.writeObject(). The same is not true for base data types and objects: they are written to the XML file, although producing different xml output than in 1.6.
Up to version 1.6 the access specifier was irrelevant. When a getter/setter existed, the content of the array was saved when it was changed by the program.
Yes I know, you should never ever make a field public for which you have a getter/setter. But things do happen and its a fact that the behaviour of XMLEncoder changed from 1.6 to 1.7.
The workaround is of course simple: Dont make your fields public. Unfortunately this is difficult when using software that is affected by this bug and for which no source code is available. It simply breaks when changing from Java 6 to Java 7 without giving any error messages.
REGRESSION. Last worked in version 6u26
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the main method from the class Fail as provided below. It contains a single int array. An instance is created, one of the array elements is changed and the array is written to the console. Then the instance is saved using XMLEncoder.writeObject(). Its read immediately afterwards and written to the console again.
When arr is private, everything works fine (the two lines at the console are identical). When arr is made public, after reading the instance with XMLDecoder, it contains the default values only, the change is lost. When run with Java 1.6_21 the code works fine regardless of the access specifier of arr.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The console should read:
f1: [1, 17, 3]
f2: [1, 17, 3]
ACTUAL -
In Java 1.7 the console reads:
f1: [1, 17, 3]
f2: [1, 2, 3]
2 is the default value, The change to 17 is lost.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
The example doesnt produce any error messages.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package fail;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
public class Fail {
public int[] arr = { 1, 2, 3 };
public Fail() {}
@Override
public String toString() {
return Arrays.toString(arr);
}
public static void main(String[] args) throws Exception {
Fail f1 = new Fail();
f1.getArr()[1] = 17;
System.out.println("f1: " + f1);
XMLEncoder enc = new XMLEncoder(new FileOutputStream("test.xml"));
enc.writeObject(f1);
enc.close();
XMLDecoder dec = new XMLDecoder(new FileInputStream("test.xml"));
Fail f2 = (Fail) dec.readObject();
dec.close();
System.out.println("f2: " + f2);
}
public int[] getArr() {
return arr;
}
public void setArr(int[] arr) {
this.arr = arr;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Dont make your fields public.