protostuff icon indicating copy to clipboard operation
protostuff copied to clipboard

ProtostuffIOUtil.toByteArray stack overflow when there is reference loop in message

Open xnslong opened this issue 6 years ago • 1 comments

When there is an reference loop in the object map, the ProtostuffIOUtil.toByteArray method will result in StackOverflowError. Following are the steps to reproduce this phenomenon.

// 1. define 2 classes, A and B, referencing each other
static class A {
    B b;
    String name;
}
static class B {
    A a;
    String name;
}

public static void main(String[] args) {
    // 2. create an object "a" and "b", with them referencing each other
    A a = new A();
    B b = new B();
    a.name = "a";
    b.name = "b";
    a.b = b;
    b.a = a;

    // 3. try to get byte array for object "a".
    Schema<A> schema = RuntimeSchema.getSchema(A.class);
    LinkedBuffer buffer = LinkedBuffer.allocate(8192);
    ProtostuffIOUtil.toByteArray(a, schema, buffer); // <-- this method call will result in StackOverflowError
}

Following is the top part of the error stack

Exception in thread "main" java.lang.StackOverflowError
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:358)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	at io.protostuff.runtime.RuntimeSchema.writeTo(RuntimeSchema.java:475)
	at io.protostuff.ProtostuffOutput.writeObject(ProtostuffOutput.java:363)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$13$1.writeTo(RuntimeUnsafeFieldFactory.java:1048)
	...

xnslong avatar Dec 26 '18 10:12 xnslong

Use GraphIOUtil instead of ProtostuffIOUtil for data with circular references

dyu avatar Dec 26 '18 10:12 dyu