сериализация объекта j2objc java.lang.NoSuchMethodException: writeReplace

Обновление. Образец проекта для воссоздания проблемы можно найти здесь: https://github.com/benf1977/j2objc-serialization-example/releases/tag/1.0

Я пытаюсь сериализовать объект на Java и передать байты моему слою Objective-C для записи в файловую систему. Мой соответствующий код Java таков:

/**
 * Created by benjamin.flynn on 10/7/15.
 */
public class TestData implements Serializable {

    private String mName;
    private int mAge;

    public TestData(String pName, int pAge) {
        mName = pName;
        mAge = pAge;
    }

    public String getName() {
        return mName;
    }

    public int getAge() {
        return mAge;
    }

    public byte[] bytes() {
        byte[] bytes = null;
        try (ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);) { // Application will break on this line when run on Xcode
            objectOutputStream.writeObject(this);
            bytes = byteOutputStream.toByteArray();
        } catch (IOException ioe) {
            System.err.println("Aww snap: " + ioe);
        }
        return bytes;
    }

}

Я протестировал этот класс на Java (для которого у меня также есть десериализатор), и он проходит. В Objective-C я делаю это:

ComMycompanyTestData *testData = [[ComMycompanyTestData alloc] initWithNSString:@"Daryl" withInt:47];
IOSByteArray *bytes = testData.bytes; // Exception here

Исключение составляет:

(lldb) po $arg1
java.lang.NoSuchMethodException: writeReplace

Соответствующая трассировка:

frame #0: 0x000000019a2cbf48 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x0000000100214bb0 MyApp `-[IOSClass getDeclaredMethod:parameterTypes:] + 124
    frame #2: 0x00000001000c9188 MyApp`JavaIoObjectStreamClass_findMethodWithIOSClass_withNSString_ + 144
    frame #3: 0x00000001000c71dc MyApp`JavaIoObjectStreamClass_createClassDescWithIOSClass_ + 984
    frame #4: 0x00000001000c909c MyApp`JavaIoObjectStreamClass_lookupStreamClassWithIOSClass_ + 88
    frame #5: 0x00000001000c8f88 MyApp`JavaIoObjectStreamClass_lookupWithIOSClass_ + 44
    frame #6: 0x00000001000c6f30 MyApp`JavaIoObjectStreamClass_createClassDescWithIOSClass_ + 300
    frame #7: 0x00000001000c909c MyApp`JavaIoObjectStreamClass_lookupStreamClassWithIOSClass_ + 88
    frame #8: 0x00000001000c8f88 MyApp`JavaIoObjectStreamClass_lookupWithIOSClass_ + 44
    frame #9: 0x00000001000c284c MyApp`JavaIoObjectOutputStream_initWithJavaIoOutputStream_ + 56
    frame #10: 0x00000001000c6a20 MyApp`new_JavaIoObjectOutputStream_initWithJavaIoOutputStream_ + 48
  * frame #11: 0x00000001000a666c MyApp`-[ComMycompanyTestData bytes](self=0x000000013fd51a50, _cmd="bytes") + 76 at TestData.java:49

Мысли о том, что может произойти?


person Ben Flynn    schedule 08.10.2015    source источник


Ответы (1)


Какую версию j2objc вы используете? Недавно мы внесли улучшения в сериализацию, и запуск вашего примера работает после добавления этого теста:

public static void main(String[] args) { TestData td = new TestData("Jane Doe", 30); byte[] serialized = td.bytes(); System.out.println("serialized: " + Arrays.toString(serialized)); }

Я запустил это с помощью переводчика/среды выполнения, созданного с использованием «make dist» для текущего источника j2objc:

$ javac TestData.java $ java TestData serialized: [-84, -19, 0, ... $ j2objc TestData.java translating TestData.java Translated 1 file: 0 errors, 0 warnings $ j2objcc TestData.m $ ./a.out TestData serialized: [-84, -19, 0, ...

person tball    schedule 08.10.2015
comment
Я попробую, спасибо. Я использую j2objc 0.9.8.2.1. - person Ben Flynn; 08.10.2015
comment
Хм. Это работает из командной строки. Это не работает, когда я работаю на устройстве iOS. Я покопаюсь в моем файле проекта на мгновение. К вашему сведению, я использую Xcode 7.0.1, iOS SDK 9.0, я включаю libjre_emul.a в свою сборку. Мне удалось передать строку из Java в Objective-C, но с помощью этого метода я немного уперся в стену. - person Ben Flynn; 08.10.2015
comment
Теперь я также попытался скомпилировать последний исходный код из GitLab, используя инструкции по включению JreEmulation в качестве подпроекта, но вижу ту же ошибку. - person Ben Flynn; 09.10.2015
comment
Я создал проект на GitHub, который демонстрирует поведение, которое я вижу (см. мой вопрос об обновлении). - person Ben Flynn; 12.10.2015
comment
Я не знаю, хорошая это новость или плохая, но ваш проект отлично работает в моей системе. Я даже скопировал println из runTest() (строка 59) в строку после byteOutputStream.toByteArray() (67), и он распечатал массив байтов, а не сбой. - person tball; 14.10.2015
comment
Хороший? =) Я посмотрю, сможет ли кто-нибудь еще из моей команды воссоздать его и снова прокомментировать. - person Ben Flynn; 14.10.2015
comment
Кажется, я нашел это: у вас есть перерыв на все исключения, установленные в отладчике? Если да, то это исключение не является ошибкой — это нормальное поведение Java. ObjectStreamClass.findMethod() проверяет каждый класс в иерархии классов на наличие метода writeReplace, вызывая Class.getDeclaredMethod() и перехватывая любые исключения NoSuchMethodException. Поэтому удалите эту точку останова для всех исключений - вместо этого вы можете прерывать работу определенного класса исключений, когда вам это нужно. - person tball; 14.10.2015
comment
Вот и все! Я никогда не играл в выполнение приложения, чтобы понять, что это некритическое исключение. Спасибо большое. - person Ben Flynn; 14.10.2015