Search code examples
javaserializationenumsj2objc

j2objc - exception when deserialize enum


I am having trouble deserializing objects that contain an enum. The object serializes without complaint, but I get an InvalidObjectException when I deserialize the object. The exception message says that there is "No enum constant com.mypackagname."

I have isolated and reproduced the problem by creating some test code based on the testSerialization() method in SerializationTest.java.

public class SerializationTest {
    private static final String TEST_FILE_NAME = "serialization-test.bin";
    public enum Gender { MALE, FEMALE }

    public void testEnumSerialization() throws IOException, ClassNotFoundException {
        Gender gender = Gender.MALE;

        // Save the enum to a file.
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(TEST_FILE_NAME));
        out.writeObject(gender);
        out.close();

        // Read back the enum.
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(TEST_FILE_NAME));
        Gender gender2 = (Gender) in.readObject();
        in.close();
    }
}

I have discovered that if I add a string value to the enum initialization in the generated Objective C code the deserialization works fine. The resulting initialize method in Obj C looks like this:

+ (void)initialize {
    if (self == [SerializationTest_Gender class]) {
        JreEnum(SerializationTest_Gender, MALE) = new_SerializationTest_Gender_initWithNSString_withInt_(@"MALE", 0);
        JreEnum(SerializationTest_Gender, FEMALE) = new_SerializationTest_Gender_initWithNSString_withInt_(@"FEMALE", 1);
        J2OBJC_SET_INITIALIZED(SerializationTest_Gender)
    }
}

Note that I added the @"MALE" and @"FEMALE", the default from the j2objc output is @"".

I have two questions. (1) Is this the correct way to enable a round trip serialization/deserialization of enums? (2) If so, is there a way to have j2objc automatically populate the string constants in the enum rather than coding them by hand?

Thanks for any help you can provide.


Solution

  • We probably broke this with a recent change eliminating redundant enum constant name strings. We had the name defined both in the enum's class initializer and in its metadata, plus we had an important request to stop making enum constants easily discovered in app binaries (apparently tech writers have been known to dump early access binaries and run strings on them to get scoops on any new features). Now the constant name is only in the metadata (no redundancy), and if an app builds with --strip-reflection, the enum has no metadata and the name becomes the enum class plus the constant's ordinal. However, serialization support was overlooked since Google apps use protocol buffers instead (faster and less version-sensitive).

    Thanks for the excellent test case, which will make it easier to fix. Please file a bug if you want to be notified when this is fixed.