Sporadic java.lang.ArrayIndexOutOfBoundsException/Can't deserialize lambda if RuntimeException is deserialized
Search before asking
- [X] I had searched in the issues and found no similar issues.
Version
0.4.1
Component(s)
Java
Minimal reproduce step
We are using fury as a replacement for jdk serialization in a java rpc application. If on the server side an exception is thrown, this exception in serialized and sent to the client. In some cases we seen and exception when the serialization is done. Thanks for your help and for that great project!
Fury setup:
var fury = Fury.builder() .withLanguage(Language.JAVA) .withRefTracking(true) .requireClassRegistration(false) .withAsyncCompilation(true).build();
Relevant parts of logs:
io.fury.serializer.LambdaSerializer.read(LambdaSerializer.java:88) io.fury.Fury.readRef(Fury.java:828) io.fury.resolver.FieldResolver.skipDataBy4(FieldResolver.java:433) com.mycompany.SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.readAndSetFields(SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.java:258) com.mycompany.SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.read(SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.java:324) com.mycompany.RemoteInvocationResultFuryRefCodec_1_815033865_718325701.readFields$(RemoteInvocationResultFuryRefCodec_1_815033865_718325701.java:111) com.mycompany.RemoteInvocationResultFuryRefCodec_1_815033865_718325701.read(RemoteInvocationResultFuryRefCodec_1_815033865_718325701.java:127) io.fury.Fury.readDataInternal(Fury.java:899) io.fury.Fury.readRef(Fury.java:801) io.fury.Fury.deserializeJavaObjectAndClass(Fury.java:1135) io.fury.Fury.deserializeJavaObjectAndClass(Fury.java:1121) com.mycompany.Serializer.deserialize(Serializer.java:35)
...
Caused by: Index -1 out of bounds for length 512 java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 512 io.fury.collection.IntArray.pop(IntArray.java:51) io.fury.resolver.MapRefResolver.reference(MapRefResolver.java:194) io.fury.builder.SerializedLambdaFuryRefCodec_1_1361449601.read(SerializedLambdaFuryRefCodec_1_1361449601.java:193) io.fury.serializer.LambdaSerializer.read(LambdaSerializer.java:85) io.fury.Fury.readRef(Fury.java:828) io.fury.resolver.FieldResolver.skipDataBy4(FieldResolver.java:433) com.mycompany.SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.readAndSetFields(SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.java:258) com.mycompany.SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.read(SomeExceptionFuryRefCompatibleCodec_1_815033865_986095905.java:324) com.mycompany.RemoteInvocationResultFuryRefCodec_1_815033865_718325701.readFields$(RemoteInvocationResultFuryRefCodec_1_815033865_718325701.java:111) com.mycompany.RemoteInvocationResultFuryRefCodec_1_815033865_718325701.read(RemoteInvocationResultFuryRefCodec_1_815033865_718325701.java:127) io.fury.Fury.readDataInternal(Fury.java:899) io.fury.Fury.readRef(Fury.java:801) io.fury.Fury.deserializeJavaObjectAndClass(Fury.java:1135) io.fury.Fury.deserializeJavaObjectAndClass(Fury.java:1121) com.mycompany.Serializer.deserialize(Serializer.java:35)
What did you expect to see?
The deserialized payload.
What did you see instead?
An ArrayIndexOutOfBoundsException.
Anything Else?
No response
Are you willing to submit a PR?
- [ ] I'm willing to submit a PR!
Hi @johannschenkl , thanks for reporting this bug. It seems that our current implementation has some inconsistency between interpreter mode and codegen mode. This has been reported in #1455, #1325 and #1176.
The fix won't be difficult. But none of this can provide reproduction code, so I can't debug to find out what's going wrong.
Will it still raise execpetion if you disabled asyncCompilation?
It would be really great if you can provide reproduction code. I try to fix it for a long time
Hi @chaokunyang, thanks for the quick response. Currently, the issue is only reproducible on a qa machine and only for some users. I was not able to reproduce it by myself. As of yet, it only happend in conjunction with a serialized RuntimeException. I'll check if disabling asyncCompilation helps and if I can somehow build a test case.
Hi @johannschenkl . Is this issue still persisits?
Hi @chaokunyang, unfortunately yes. I'm still trying to get a reproducer working.
We're self-managing Fury in a ThreadLocal, is that the issue, maybe?
private static final ThreadLocal<Fury> THE_FURY = ThreadLocal.withInitial(() -> {
var fury = Fury.builder().withLanguage(Language.JAVA)
.withRefTracking(true)
.requireClassRegistration(false)
.withAsyncCompilation(true)
.suppressClassRegistrationWarnings(true) // as checker is enabled, see below
.build();
fury.getClassResolver().setClassChecker(...);
return fury;
});
I know there's also the ...buildThreadSafeFury/buildThreadLocalFury implementations. But we did not see a way to register a classchecker on them.
This is right, or you can use org.apache.fury.ThreadLocalFury#ThreadLocalFury, which let you to set anything in the factory
Hi @chaokunyang, sorry for the late response. After using the provided factory & disabling async compilation, the issue did not show up again.