Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Random Deserialization Problem with fst 2.57 #270

Open
furti opened this issue Nov 30, 2018 · 29 comments · May be fixed by #329
Open

Random Deserialization Problem with fst 2.57 #270

furti opened this issue Nov 30, 2018 · 29 comments · May be fixed by #329
Assignees
Labels

Comments

@furti
Copy link

furti commented Nov 30, 2018

We are using fast-serialization now for over a year in our application and it worked like a charm. But with the last version deployed this week, we switched from version 2.47 to 2.57. Everything worked fine in our QA enviroment. But in Production things got weird.

Basically we use the library to serialize and deserialize sessions to and from a Relational DB. In PROD the deserializing produces strange results in some cases. Mostly a java.lang.String.equals call failed inside the string class at line 982 int n = value.length;. The internal value field of the String was null. This should never happen. Except when you mess up the String with reflection. But we were pretty sure we don't do this ;)
It went that far, that the jvm terminated with a Sementation Error when such maleformed data was accessed.

I wrote a small programm that checked every session in the database. And there where indeed some sessions that failed. I removed them and let the program run again. But wait...now other sessions, that where valid in the first run, failed in the second run. But the binary data was exactly the same 😲

Now we had the idea to try it with the older version 2.47 we used before. And what should I say. The same sessions, written with version 2.57, could be read with version 2.47 without any problem. So the problem must lay in the deserialization logic of fst 2.57.

I tracked it down now to a set of 3 Session objects. When they are deserialized in a specific order, the deserialization does pretty weird stuff for the last sesison object. Most noticalbe it sets a field of type "String" to a List of other Objects.

Some things to note

  • Happens on Windows 10 and Linux systems
  • Reproducable on oralce jdk 1.8_181-x64 and
openjdk version "1.8.0-adoptopenjdk"
OpenJDK Runtime Environment (build 1.8.0-adoptopenjdk-_2018_05_19_00_59-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)
  • We use fst on a server and use a ThreadLocal like suggested by the docs
    private static final ThreadLocal<DefaultCoder> CODERS = ThreadLocal.withInitial(() -> new DefaultCoder());
    But my test Testcase shows that it also happens in a simply main class without any threads and also with FSTOBjectInput Instances obtained by the FSTConfiguration. As long as you reuse a Instance it might happen from time to time.

TestCase

I have a TestCase ready. But I have to make sure first, that I'm allowed to upload it to github as it contains code written for our project at work.
I will update this issue as soon as I have uploaded the test case.

The test case including a description is available at https://github.com/furti/fst-deserialization-problem

But maybe someone has the same Problem or has an idea what could be the cause for this strange behaviour?
I'm pretty sure it must be something in the library. But it could also be something we do wrong. So excuse me if that is the case :)

@RuedigerMoeller RuedigerMoeller self-assigned this Dec 2, 2018
@RuedigerMoeller
Copy link
Owner

RuedigerMoeller commented Dec 2, 2018

awaiting your test case. Meanwhile try disabling the use of unsafe to at least get an exception instead of a segfault. Penalty is 10-20% performance loss

@furti
Copy link
Author

furti commented Dec 3, 2018

@RuedigerMoeller I updated the initial bug description and added a link to the test case. If you need more informations let me know :)

@andrewl102
Copy link

Have you tried to see what happens if you preregister each of the classes?
It might be the same issue as #254 / due to #235, potentially multiple threads are not needed to reproduce the problem as the symptoms are quite similar.

Additionally, preregistering the classes would significantly reduce the size of your serialized data so it would be advised anyway.

@furti
Copy link
Author

furti commented Dec 28, 2018

I tried to preregister the classes in my testcase. It makes no difference. But I think it is too late to register them when deserializing a stream written without registered classes.

The problem is, that it only happens from time to time in our production system. There is to less traffic in the test system. So we can't easily test, if preregistering classes makes a difference.

I hope the test case, as it is, will help someone with deep understanding of the library to find the problem :)

@slovdahl
Copy link

slovdahl commented Jan 23, 2019

We might be seeing something similar. We're still quite early in the debugging process, so not really sure which part of the stack to blame just yet. At the moment, we don't have any way of reliably reproducing our problem.

Anyway, we're using fst in combination with netty for RPC. No unsafe (FSTConfiguration.createDefaultConfiguration()) or other special configuration of fst. Versions in use:

  • fst 2.57
  • netty 4.1.22.Final (also tested 4.1.32.Final)
  • OpenJDK 8 (8u171-b11 and 8u202-b01 tested)
  • Ubuntu 14.04

This is what our deserialization looks like:

class FstDecoder extends io.netty.handler.codec.LengthFieldBasedFrameDecoder {

    FstDecoder( int maxObjectSize ) {
        super( maxObjectSize, 0, 4, 0, 4 );
    }

    @Override
    protected Object decode( io.netty.channel.ChannelHandlerContext ctx,
                             io.netty.buffer.ByteBuf in ) throws Exception {

        io.netty.buffer.ByteBuf frame = (io.netty.buffer.ByteBuf)super.decode( ctx, in );
        if ( frame == null ) {
            return null;
        }

        try {
            byte[] bytes = ByteBufUtil.getBytes( frame );
            return fstConfiguration.getObjectInput( bytes ).readObject();
        }
        finally {
            frame.release();
        }
    }
}

And this is the error we're seeing:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fb4b35b64d5, pid=18866, tid=0x00007fb42d9f7700
#
# JRE version: OpenJDK Runtime Environment (8.0_171-b11) (build 1.8.0_171-8u171-b11-2~14.04-b11)
# Java VM: OpenJDK 64-Bit Server VM (25.171-b11 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x5fa4d5]

Stack: [0x00007fb42d8f7000,0x00007fb42d9f8000],  sp=0x00007fb42d9f57b0,  free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x5fa4d5]
V  [libjvm.so+0x9030c1]
v  ~RuntimeStub::_new_array_Java
J 14827 C2 com.google.common.collect.ImmutableSet.copyOf([Ljava/lang/Object;)Lcom/google/common/collect/ImmutableSet; (52 bytes) @ 0x00007fb49db88ee8 [0x00007fb49db88d00+0x1e8]
J 12013 C2 sun.reflect.GeneratedMethodAccessor72.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (61 bytes) @ 0x00007fb49f5b9710 [0x00007fb49f5b96c0+0x50]
J 11235 C2 org.nustaq.serialization.FSTObjectInput.readObjectCompatible(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;Ljava/lang/Object;)Ljava/lang/Object; (35 bytes) @ 0x00007fb49f466a54 [0x00007fb49f466120+0x934]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f309c [0x00007fb49e1f29a0+0x6fc]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f3190 [0x00007fb49e1f29a0+0x7f0]
J 11238 C2 org.nustaq.serialization.FSTObjectInput.instantiateArray(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;I)Ljava/lang/Object; (9 bytes) @ 0x00007fb49d82e508 [0x00007fb49d82e000+0x508]
J 7152 C2 org.nustaq.serialization.FSTObjectInput.instantiateSpecialTag(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;IB)Ljava/lang/Object; (359 bytes) @ 0x00007fb49e2e441c [0x00007fb49e2e1700+0x2d1c]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f2a68 [0x00007fb49e1f29a0+0xc8]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 11235 C2 org.nustaq.serialization.FSTObjectInput.readObjectCompatible(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;Ljava/lang/Object;)Ljava/lang/Object; (35 bytes) @ 0x00007fb49f466968 [0x00007fb49f466120+0x848]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f309c [0x00007fb49e1f29a0+0x6fc]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f3190 [0x00007fb49e1f29a0+0x7f0]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f3190 [0x00007fb49e1f29a0+0x7f0]
J 11238 C2 org.nustaq.serialization.FSTObjectInput.instantiateArray(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;I)Ljava/lang/Object; (9 bytes) @ 0x00007fb49d82e508 [0x00007fb49d82e000+0x508]
J 7152 C2 org.nustaq.serialization.FSTObjectInput.instantiateSpecialTag(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;IB)Ljava/lang/Object; (359 bytes) @ 0x00007fb49e2e441c [0x00007fb49e2e1700+0x2d1c]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f2a68 [0x00007fb49e1f29a0+0xc8]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 11235 C2 org.nustaq.serialization.FSTObjectInput.readObjectCompatible(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;Ljava/lang/Object;)Ljava/lang/Object; (35 bytes) @ 0x00007fb49f466968 [0x00007fb49f466120+0x848]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f309c [0x00007fb49e1f29a0+0x6fc]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f3190 [0x00007fb49e1f29a0+0x7f0]
J 13705 C2 org.nustaq.serialization.serializers.FSTArrayListSerializer.instantiate(Ljava/lang/Class;Lorg/nustaq/serialization/FSTObjectInput;Lorg/nustaq/serialization/FSTClazzInfo;Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;I)Ljava/lang/Object; (71 bytes) @ 0x00007fb49f5a1044 [0x00007fb49f5a0c00+0x444]
J 12503 C2 org.nustaq.serialization.FSTObjectInput.instantiateAndReadWithSer(Ljava/lang/Class;Lorg/nustaq/serialization/FSTObjectSerializer;Lorg/nustaq/serialization/FSTClazzInfo;Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;I)Ljava/lang/Object; (201 bytes) @ 0x00007fb49f7c8100 [0x00007fb49f7c80a0+0x60]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f2c84 [0x00007fb49e1f29a0+0x2e4]
J 10171 C2 org.nustaq.serialization.FSTObjectInput.readObjectFields(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Lorg/nustaq/serialization/FSTClazzInfo;[Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;Ljava/lang/Object;II)V (538 bytes) @ 0x00007fb49eea38a0 [0x00007fb49eea3680+0x220]
J 7099 C2 org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(Lorg/nustaq/serialization/FSTClazzInfo$FSTFieldInfo;)Ljava/lang/Object; (189 bytes) @ 0x00007fb49e1f3190 [0x00007fb49e1f29a0+0x7f0]
J 22704 C2 io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(Lio/netty/channel/ChannelHandlerContext;Lio/netty/buffer/ByteBuf;Ljava/util/List;)V (23 bytes) @ 0x00007fb4a10e8d48 [0x00007fb4a10e7560+0x17e8]
J 17919 C2 io.netty.handler.codec.ByteToMessageDecoder.channelRead(Lio/netty/channel/ChannelHandlerContext;Ljava/lang/Object;)V (317 bytes) @ 0x00007fb4a03ca4dc [0x00007fb4a03c9b40+0x99c]
J 17236 C2 io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(Lio/netty/channel/ChannelHandlerContext;Ljava/lang/Object;)V (9 bytes) @ 0x00007fb49fe1a82c [0x00007fb49fe1a660+0x1cc]
J 17450 C2 io.netty.channel.nio.NioEventLoop.processSelectedKey(Ljava/nio/channels/SelectionKey;Lio/netty/channel/nio/AbstractNioChannel;)V (142 bytes) @ 0x00007fb4a02553d8 [0x00007fb4a0254520+0xeb8]
J 19198% C2 io.netty.channel.nio.NioEventLoop.run()V (221 bytes) @ 0x00007fb49f0804a8 [0x00007fb49f07fe40+0x668]
j  io.netty.util.concurrent.SingleThreadEventExecutor$5.run()V+44
j  io.netty.util.concurrent.FastThreadLocalRunnable.run()V+4
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub
V  [libjvm.so+0x639a9a]
V  [libjvm.so+0x637154]
V  [libjvm.so+0x63774a]
V  [libjvm.so+0x67700e]
V  [libjvm.so+0x9b1c58]
V  [libjvm.so+0x865582]
C  [libpthread.so.0+0x8184]  start_thread+0xc4

@perlun
Copy link

perlun commented Jan 24, 2019

See #235, we discovered that issue and it seems to be our root cause.

@perlun
Copy link

perlun commented Feb 4, 2019

@furti We have debugged our issue to great length and concluded that it seems to be related to our use of the G1GC garbage collector. Do you happen to be running it in production?

@furti
Copy link
Author

furti commented Feb 6, 2019

Currently we use openjdk 8 without setting the GC explicit. When the error occured we used Oracle JRE 8 ,Also without changing the GC. So I assume we don't have G1GC enabled.

I also checked locally by explicitly starting Eclipse with a different GC. And also the started test program has no GC set and runs on openjdk 8. But the error occurs.

So I think our Problem has nothing to do with the GC. But I could be wrong.

@perlun
Copy link

perlun commented Feb 7, 2019

@furti Ok, maybe these are two different issues. For reference, my test repro is here https://github.com/perlun/fst-concurrency-issue - it would be interesting to see if this scenario fails for you without tweaking the GC setting. (change it in build.gradle to not override the GC being used)

With the default GC, I have not seen this test failing on Java 8 so it would be very interesting to see how it behaves for you.

@chrisco484
Copy link

@furti We have debugged our issue to great length and concluded that it seems to be related to our use of the G1GC garbage collector. Do you happen to be running it in production?

Do you have String deduplication turned on as well as G1GC?

We're seeing a concurrency issue "failed to read next byte" under heavy load which has been mentioned in a few other issues - and all mention G1GC strategy - I'm wondering if people also have string duplication turned on which requires G1GC.

@perlun
Copy link

perlun commented Aug 29, 2019

@chrisco484

Do you have String deduplication turned on as well as G1GC?

At the moment, we use -XX:+UseStringDeduplication yes. I discussed this with @slovdahl and to the best of our knowledge, we have reproduced this without string deduplication active - see #274 for my repro repository.

@perlun
Copy link

perlun commented Aug 29, 2019

(For the moment, we are staying away from FST because of the severity of this bug. We cannot have the JVM crashing randomly; it's better to live with a few % lower performance and use another serialization library until this gets properly resolved on the FST side.)

@chrisco484
Copy link

(For the moment, we are staying away from FST because of the severity of this bug. We cannot have the JVM crashing randomly; it's better to live with a few % lower performance and use another serialization library until this gets properly resolved on the FST side.)

To my understanding this concurrency issue only occurs when you reuse the streams as specified in the doco for improved speed. Does that mean it is still possible to use FST concurrently so long as we don't take advantage of the reusable stream objects?

@perlun
Copy link

perlun commented Sep 6, 2019

@chrisco484 Unfortunately, no. If you look at this code in my repro repository, we instantiate new streams for each iteration in the loop. Even with this approach, we run into concurrency issues.

If you find ways to workaround it, please let me know.

        for ( int i = 0; i < 1_000_000; i++ ) {
            futures.add( pool.submit( () -> {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                try {
                    writeObject( testObject, stream );
                    readObject( new ByteArrayInputStream( stream.toByteArray() ) );
                }
                catch ( Exception e ) {
                    System.err.println( "ERROR" + e );
                    throw new RuntimeException( e );
                }

            } ) );
        }

@chrisco484
Copy link

chrisco484 commented Oct 12, 2019

@chrisco484 Unfortunately, no. If you look at this code in my repro repository, we instantiate new streams for each iteration in the loop. Even with this approach, we run into concurrency issues.

Oh wow, that's a worry. I see your writeObject and readObject methods are creating completely new instances and yet there's still a concurrency issue!.

That shared FSTConfiguration object must be sharing objects between the threads in a "not totally threadsafe" way :)

I think I just found something extra that I'm tempting fate with: In my app a library uses FST and so does the main app. They both instantiate separate FSTConfiguration objects and the various threads would be touching both - that might complicate the threading semantics even more because FSTConfiguration may be written assuming that there is only ever ONE FSTConfiguration instance within any running app and possibly thread locals assume complete monopolization of their resources but if there is another FSTConfiguration and it has been touched by the same thread then that could have serious consequences.

I just checked the source code - when I have multiple libraries that need to use the FST library I think I need to use FSTConfiguration.getDefaultConfiguration() rather than calling FSTConfiguration.createDefaultConfiguration().

If using the latter method each library will be creating its own config instance (which may not be good in a multi threaded environment - I've seen byte stream with completely wrong data - data produced by a different library running in the same JVM - weird.)

From the source code below, if I use getDefaultConfiguration instead then the JVM will only end up with a single FSTConfiguration instance - which is probably how its designed to work.

static AtomicBoolean conflock = new AtomicBoolean(false);
static FSTConfiguration singleton;
public static FSTConfiguration getDefaultConfiguration() {
do { } while ( !conflock.compareAndSet(false, true) );
try {
if (singleton == null)
singleton = createDefaultConfiguration();
return singleton;
} finally {
conflock.set(false);
}
}

@tlamr
Copy link

tlamr commented Dec 13, 2019

This caused me grey hair. Failing on prod on distributed highly-concurrent system where computations communicate through redisson where FST is the default codec.

We had to switch to other codec.

@chrisco484
Copy link

chrisco484 commented Dec 13, 2019

We had to switch to other codec.

@tlamr Which one did you switch to?

We're also evaluating alternatives to FST because, even though the concept and performance is awesome, we just can't have a crucial tech component that fails under highly concurrent loads and it seems no fix is in sight given the time that has elapsed since these issues were first raised.

@tlamr
Copy link

tlamr commented Dec 14, 2019

I switched it to std java serializer, since this one worked out of the box for the whole app and we needed some asap fix.
It seems that we would need to do some changes to be able to use other codecs (kryo4 wanted no arg constructors, json based also wanted some additional things,...)
I plan to investigate it further, but so far haven't dig into it.

@chrisco484 How is going the evalutation of alternatives? Any preference to some other codec?

I fully agree with your view on correctness and speed, we are in the very same situation it seems :)

@chrisco484
Copy link

chrisco484 commented Dec 14, 2019 via email

@denis-bogdanas
Copy link

What about version 2.47 does it have this issue? Or it has others?

@tlamr
Copy link

tlamr commented Jan 14, 2020

We moved to kryo.

@perlun
Copy link

perlun commented Jan 14, 2020

For reference, kryo is here: https://github.com/EsotericSoftware/kryo

@autoans
Copy link

autoans commented Aug 13, 2020

@furti was this problem solved? we are facing similar issue and string.Equals causes occasional crashes.

kryo is not an in-place replacement for java serializer.

@vlk32
Copy link

vlk32 commented Sep 10, 2020

Hello all,

I've a similar problem, and maybe it's not problem of concurrency.

My project contains 3 serialisable object instances (data of internal knowledge base), each containing Map<String, Codelist[]>. Class Codelist contains another map-structure Map<String, Set<String>>. Before serialisation there is only strings inside of that set. During compilation I serialise that objects to the three (data) files. In another project I load that files back into memory.

Sometimes it deserialise with wrong types, so Set<String> contains objects with other types as a String, sometimes there is another class, sometimes there is map ... It happends also in unit-test, when the loading of data is called by one thread. And it give different result depending on loading order of that files.

My workaround is to use new instance of FSTConfiguration for each call.

Part of my code :

    @Override
    public <T> T load(Class<T> cls, InputStream is) {
        try (FSTObjectInput ois = new FSTObjectInput(is, createNewConfiguration())) {
            return (T) ois.readObject(cls);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public <T> void save(T obj, OutputStream os) throws IOException {
        try (FSTObjectOutput oos = new FSTObjectOutput(os, createNewConfiguration())) {
              oos.writeObject(obj);
        }
    }

    private FSTConfiguration createNewConfiguration() {
        return FSTConfiguration.createDefaultConfiguration();
    }
}

@theRealAph
Copy link

Should be fixed by #311 . Please check.

@jschewebbn
Copy link

Using a configuration for each serialize call works, however it can be quite slow and memory intensive. So I tried using one per thread and ran into issues. My serializer is on one system and my deserializer is on a different system. Is it possible that FST is caching information in different order on the two systems and therefore causing the configurations to be out of sync?

@theRealAph
Copy link

Using a configuration for each serialize call works, however it can be quite slow and memory intensive. So I tried using one per thread and ran into issues. My serializer is on one system and my deserializer is on a different system. Is it possible that FST is caching information in different order on the two systems and therefore causing the configurations to be out of sync?

Did you check if the fix in #311 works?

@jschewebbn
Copy link

I'm still on Java 11, so I can't test any of the new releases. Note that I have a configuration per thread, so there is no concurrency issue.

@theRealAph
Copy link

I'm still on Java 11, so I can't test any of the new releases.

The patch should be a trivial backport to any release.

Note that I have a configuration per thread, so there is no concurrency issue.

Sure, OK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.