FST (de) хорошо сериализуется в JSON, однако имеет проблемы с конфигурацией по умолчанию
Мы используем FST (быстрая сериализация) для одновременного размещения на диске больших объемов объектов и последующего их чтения. Объекты сами по себе имеют сложную структуру и содержат то, что не так: примитивы, сложные типы, массивы и их наборы. Проблема в том, что с настройкой FST по умолчанию (FSTConfiguration.createDefaultConfiguration()
) мы наблюдаем исключения десериализации, такие как:
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
at org.nustaq.serialization.FSTObjectInput.readObjectCompatibleRecursive(FSTObjectInput.java:609) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectCompatibleRecursive(FSTObjectInput.java:598) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectCompatible(FSTObjectInput.java:574) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:559) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:374) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectInternal(FSTObjectInput.java:331) ~[fst-2.55.jar:na]
at org.nustaq.serialization.serializers.FSTCollectionSerializer.instantiate(FSTCollectionSerializer.java:92) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.instantiateAndReadWithSer(FSTObjectInput.java:501) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:370) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectFields(FSTObjectInput.java:712) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:566) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:374) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObjectInternal(FSTObjectInput.java:331) ~[fst-2.55.jar:na]
at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:311) ~[fst-2.55.jar:na]
at com.agilertech.graph.dao.disk.readers.EntityStorageReader.readObject(EntityStorageReader.java:21) ~[main/:na]
...our code there...
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_91]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[na:1.8.0_91]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_91]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[na:1.8.0_91]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_91]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_91]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_91]
Caused by: java.io.InvalidObjectException: can't deserialize enum
at java.lang.Enum.readObject(Enum.java:251) ~[na:1.8.0_91]
... 35 common frames omitted
Это происходит примерно в 5 раз из 100. Хотя, если переключиться на конфигурацию JSON (FSTConfiguration.createJsonConfiguration()
), все проблемы исчезают - никаких исключений во время (де) сериализации вообще.
Я попытался найти основную причину с помощью отладки, похоже, что в некоторых случаях FST переключается на useCompatibleMode
по какой-то причине, а затем пытается создать экземпляр Enum
путем десериализации этого. Я также пытался воспроизвести эту проблему в качестве теста, но мне не повезло - сопоставимые структуры данных, которые я создаю, не вызывают таких проблем.
Есть ли проблема в нашей доменной структуре / неправильное использование FST, или это может быть ошибка?
Как примечание, все классы домена, которые мы используем, правильно реализуют Serializable
,
1 ответ
Я получал похожую ошибку, когда отправлял сериализованные объекты через сокет. Я нашел следующую документацию, которая решила мои проблемы (в основном отправка размера, затем объекта).
Огромные объекты / чанки, потоковый ввод / вывод:
Закодированные объекты записываются в базовый поток после закрытия / очистки FSTOutputStream. И наоборот, FSTInput считывает основной поток кусками, пока не начнет декодирование. Это означает, что вы не можете читать напрямую из блокирующих потоков (например, возвращаемых Socket). Пример того, как это решить.
Я знаю пользователей, которые все еще предпочитают FST для очень больших графов объектов. Максимальный размер определяется по индексу int, поэтому максимальный размер графа объекта составляет ~1,5 ГБ.