diff --git a/src/com/esotericsoftware/kryo/serializers/ReflectField.java b/src/com/esotericsoftware/kryo/serializers/ReflectField.java index 4e91f5f31..e01432fce 100644 --- a/src/com/esotericsoftware/kryo/serializers/ReflectField.java +++ b/src/com/esotericsoftware/kryo/serializers/ReflectField.java @@ -92,6 +92,12 @@ public void write (Output output, Object object) { } catch (KryoException ex) { ex.addTrace(name + " (" + object.getClass().getName() + ")"); throw ex; + } catch (StackOverflowError ex) { + throw new KryoException( + "A StackOverflow occurred. The most likely cause is that your data has a circular reference resulting in " + + "infinite recursion. Try enabling references with Kryo.setReferences(true). If your data structure " + + "is really more than " + kryo.getDepth() + " levels deep then try increasing your Java stack size.", + ex); } catch (Throwable t) { KryoException ex = new KryoException(t); ex.addTrace(name + " (" + object.getClass().getName() + ")"); diff --git a/test/com/esotericsoftware/kryo/serializers/FieldSerializerTest.java b/test/com/esotericsoftware/kryo/serializers/FieldSerializerTest.java index dda29d706..7e06c7305 100644 --- a/test/com/esotericsoftware/kryo/serializers/FieldSerializerTest.java +++ b/test/com/esotericsoftware/kryo/serializers/FieldSerializerTest.java @@ -705,6 +705,22 @@ public void testDeep () { roundTrip(1440, root); } + @Test + public void testCircularReference () { + kryo.register(CircularReference.class); + kryo.register(CircularReference.Inner.class); + + CircularReference instance = new CircularReference(); + try { + roundTrip(1, instance); + } catch (KryoException ex) { + assertTrue(ex.getMessage().contains("A StackOverflow occurred.")); + return; + } + + fail("Exception was expected"); + } + public static class DefaultTypes { // Primitives. public boolean booleanField; @@ -1279,4 +1295,17 @@ public boolean equals (Object obj) { return true; } } + + static class CircularReference { + Inner b = new Inner(this); + + static class Inner { + CircularReference a; + + public Inner(CircularReference a) { + this.a = a; + } + } + } + }