Fixed - Kryo5Codec fails to (de)serialize Object without no-args constructor (regression since 3.19.2) #4834

pull/4843/head
Nikita Koksharov 2 years ago
parent 72076eca44
commit c42b997014

@ -27,6 +27,7 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import org.objenesis.instantiator.ObjectInstantiator;
import org.objenesis.strategy.StdInstantiatorStrategy;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.handler.State;
import org.redisson.client.protocol.Decoder;
@ -34,7 +35,6 @@ import org.redisson.client.protocol.Encoder;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.util.UUID;
import java.util.regex.Pattern;
@ -53,6 +53,8 @@ public class Kryo5Codec extends BaseCodec {
private static class SimpleInstantiatorStrategy implements org.objenesis.strategy.InstantiatorStrategy {
private final StdInstantiatorStrategy ss = new StdInstantiatorStrategy();
@Override
public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
// Reflection.
@ -77,22 +79,7 @@ public class Kryo5Codec extends BaseCodec {
} catch (Exception ignored) {
}
if (type.isMemberClass() && !Modifier.isStatic(type.getModifiers()))
throw new KryoException("Class cannot be created (non-static member class): " + className(type));
else {
StringBuilder message = new StringBuilder("Class cannot be created (missing no-arg constructor): " + className(type));
if (type.getSimpleName().equals("")) {
message
.append(
"\nNote: This is an anonymous class, which is not serializable by default in Kryo. Possible solutions:\n")
.append("1. Remove uses of anonymous classes, including double brace initialization, from the containing\n")
.append(
"class. This is the safest solution, as anonymous classes don't have predictable names for serialization.\n")
.append("2. Register a FieldSerializer for the containing class and call FieldSerializer\n")
.append("setIgnoreSyntheticFields(false) on it. This is not safe but may be sufficient temporarily.");
}
throw new KryoException(message.toString());
}
return ss.newInstantiatorOf(type);
}
}

@ -0,0 +1,48 @@
package org.redisson.codec;
import io.netty.buffer.ByteBuf;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
public class Kryo5CodecTest {
public static final class TestData {
private String value;
public TestData(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@Test
public void test() throws IOException {
Kryo5Codec cc = new Kryo5Codec();
LinkedHashSet<String> v11 = new LinkedHashSet<>();
v11.add("123");
ByteBuf v1 = cc.getValueEncoder().encode(v11);
LinkedHashSet<String> v11_1 = (LinkedHashSet<String>) cc.getValueDecoder().decode(v1, null);
Assertions.assertThat(v11_1).containsOnly("123");
LinkedHashMap<String, String> v12 = new LinkedHashMap<>();
v12.put("1", "2");
ByteBuf v2 = cc.getValueEncoder().encode(v12);
LinkedHashMap<String, String> v12_1 = (LinkedHashMap<String, String>) cc.getValueDecoder().decode(v2, null);
Assertions.assertThat(v12_1).containsEntry("1", "2");
TestData v13 = new TestData("123");
ByteBuf v3 = cc.getValueEncoder().encode(v13);
TestData v13_3 = (TestData) cc.getValueDecoder().decode(v3, null);
Assertions.assertThat(v13_3.getValue()).isEqualTo("123");
}
}
Loading…
Cancel
Save