Search before asking
Version
Fory 1.7.1, linux, openjdk 25
Component(s)
Java
Minimal reproduce step
Compile and run this example with fory 1.7.1
package org.example;
import org.apache.fory.Fory;
import org.apache.fory.ThreadLocalFory;
import org.apache.fory.config.Language;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class MainPure {
public static void main() {
ThreadLocalFory fory = Fory.builder()
.withLanguage(Language.JAVA)
.requireClassRegistration(false)
.withRefTracking(true)
.withXlang(false)
.withCompatible(false)
.buildThreadLocalFory();
Container<Container<Integer>> one = new Container<>(new Container<>(1, 2, 3), new Container<>(4, 5, 6));
try {
Object o = fory.deserialize(fory.serialize(one));
System.out.println(o);
} catch (Throwable e) {
System.out.println("failed");
e.printStackTrace(System.out);
}
}
static class Container<T> implements Externalizable {
Object[] item;
public Container(T... t) {
item = t;
}
public Container() {
item = new Object[]{};
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(item.length);
for (Object t : item) {
out.writeObject(t);
}
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
int length = in.readInt();
item = new Object[length];
for (int i = 0; i < length; i++) {
item[i] = in.readObject();
}
}
}
}
What did you expect to see?
No exception should be emitted
What did you see instead?
`java.lang.NullPointerException: Cannot invoke "org.apache.fory.context.WriteContext.writeRef(Object)" because "this.writeContext" is null`
org.apache.fory.exception.SerializationException: java.lang.NullPointerException: Cannot invoke "org.apache.fory.context.WriteContext.writeRef(Object)" because "this.writeContext" is null
at org.apache.fory.Fory.processSerializationError(Fory.java:391)
at org.apache.fory.Fory.serialize(Fory.java:358)
at org.apache.fory.Fory.serialize(Fory.java:319)
at org.apache.fory.ThreadLocalFory.serialize(ThreadLocalFory.java:96)
at org.example.MainPure.main(MainPure.java:25)
Caused by: java.lang.NullPointerException: Cannot invoke "org.apache.fory.context.WriteContext.writeRef(Object)" because "this.writeContext" is null
at org.apache.fory.io.MemoryBufferObjectOutput.writeObject(MemoryBufferObjectOutput.java:60)
at org.example.MainPure$Container.writeExternal(MainPure.java:50)
at org.apache.fory.serializer.ExternalizableSerializer.write(ExternalizableSerializer.java:50)
at org.apache.fory.serializer.ExternalizableSerializer.write(ExternalizableSerializer.java:32)
at org.apache.fory.context.WriteContext.writeData(WriteContext.java:663)
at org.apache.fory.context.WriteContext.writeRef(WriteContext.java:480)
at org.apache.fory.context.WriteContext.writeRootRef(WriteContext.java:537)
at org.apache.fory.Fory.serialize(Fory.java:355)
... 3 more
Anything Else?
This happens due to handling of objectOutput in ExternalizableSerializer.write
When value.writeExternal(objectOutput); is done the finally block calls objectOutput.clearWriteContext(); which sets writeContext = null. The following chain of events happens in this example:
Container<Container<Integer>> (outer container) starts serializing it's first element
- Inner
Container<Integer> finishes writeExternal and objectOutput.clearWriteContext(); is called
Container<Container<Integer>> (outer container) starts serializing it's second element
- Because
objectOutput is the same in poth calls of ExternalizableSerializer.write when returning to Container<Container<Integer>>.writeExternal the field writeContext is now null and exception happens when writeObject is called and gets to serializing second internal container
I also expect the same thing to happen with ExternalizableSerializer.read and readContext.
I'm not sure what intended logic here is, but it seems like MemoryBufferObjectOutput objects should be created for each value.writeExternal call instead of this attempted reuse (so each call to writeExternal gets it's own object)
Are you willing to submit a PR?
Search before asking
Version
Fory 1.7.1, linux, openjdk 25
Component(s)
Java
Minimal reproduce step
Compile and run this example with fory 1.7.1
What did you expect to see?
No exception should be emitted
What did you see instead?
`java.lang.NullPointerException: Cannot invoke "org.apache.fory.context.WriteContext.writeRef(Object)" because "this.writeContext" is null`
Anything Else?
This happens due to handling of
objectOutputinExternalizableSerializer.writeWhen
value.writeExternal(objectOutput);is done thefinallyblock callsobjectOutput.clearWriteContext();which setswriteContext = null. The following chain of events happens in this example:Container<Container<Integer>>(outer container) starts serializing it's first elementContainer<Integer>finisheswriteExternalandobjectOutput.clearWriteContext();is calledContainer<Container<Integer>>(outer container) starts serializing it's second elementobjectOutputis the same in poth calls ofExternalizableSerializer.writewhen returning toContainer<Container<Integer>>.writeExternalthe fieldwriteContextis now null and exception happens whenwriteObjectis called and gets to serializing second internal containerI also expect the same thing to happen with
ExternalizableSerializer.readandreadContext.I'm not sure what intended logic here is, but it seems like
MemoryBufferObjectOutputobjects should be created for eachvalue.writeExternalcall instead of this attempted reuse (so each call towriteExternalgets it's own object)Are you willing to submit a PR?