code: package net.openhft.chronicle.map;
  
  import net.openhft.chronicle.hash.serialization.impl.CommonMarshallableReaderWriter;
  import net.openhft.chronicle.wire.BytesInBinaryMarshallable;
  import net.openhft.chronicle.wire.Marshallable;
  import net.openhft.chronicle.wire.SelfDescribingMarshallable;
  import net.openhft.chronicle.wire.WireOut;
  import org.jetbrains.annotations.NotNull;
  import org.junit.Test;
  
  import java.io.Serializable;
  import java.util.stream.Collectors;
  import java.util.stream.IntStream;
  
  import static org.junit.Assert.*;
  
  // From https://github.com/OpenHFT/Chronicle-Map/issues/183
  public class SerializableTest {
      @Test
      public void test1() {
          for (int i = 512; i < 514; i++) {
              System.out.println(i);
              try (ChronicleMap<Integer, Foo> map = ChronicleMapBuilder.of(Integer.class, Foo.class)
                      .name("foo")
                      .averageValueSize(32 + i * 2)
                      .entries(10)
                      .create()) {
  
                  map.put(1, new Foo(i));
                  map.get(1);
                  map.put(2, new Foo(i + 1));
                  assertEquals(i + 2, map.get(2).x.length());
              }
          }
      }
  
      @Test
      public void test2() {
          ChronicleMap<Integer, Foo> map = ChronicleMapBuilder.of(Integer.class, Foo.class)
                  .name("bar")
                  .averageValueSize(4096)
                  .entries(10)
                  .create();
  
          String expected = expected();
  
          Foo value = new Foo(expected);
          map.put(1, value);
          String actual = map.get(1).x;
  
          assertEquals(expected, actual);
      }
  
      @Test
      public void test2b() {
          ChronicleMap<Integer, Bar> map = ChronicleMapBuilder.simpleMapOf(Integer.class, Bar.class)
                  .name("bar")
                  .averageValueSize(4096)
                  .entries(10)
                  .create();
  
          String expected = expected();
  
          Bar value = new Bar(expected);
          map.put(1, value);
          assertFalse(value.usesSelfDescribingMessage());
          assertFalse(value.writeMarshallableWireOutCalled);
          String actual = map.get(1).x;
  
          assertEquals(expected, actual);
      }
  
      @Test
      public void test2c() {
          ChronicleMap<Integer, Bar2> map = ChronicleMapBuilder.simpleMapOf(Integer.class, Bar2.class)
                  .name("bar")
                  .averageValueSize(1024)
                  .entries(10)
                  .create();
  
          String expected = expected();
  
          Bar2 value = new Bar2(expected);
          map.put(1, value);
          assertTrue(value.usesSelfDescribingMessage());
          assertFalse("we call bytes marshallable in this case", value.writeMarshallableWireOutCalled);
          String actual = map.get(1).x;
  
          assertEquals(expected, actual);
      }
  
      @Test
      public void test2d() {
          // if you create the Map of value type == Marshallable then it will use a TypedMarshallableReaderWriter
          ChronicleMap<Integer, Marshallable> map = ChronicleMapBuilder.simpleMapOf(Integer.class, Marshallable.class)
                  .name("bar")
                  .averageValueSize(1024)
                  .entries(10)
                  .create();
  
          String expected = expected();
  
          Bar2 value = new Bar2(expected);
          map.put(1, value);
          assertTrue(value.usesSelfDescribingMessage());
          assertTrue(value.writeMarshallableWireOutCalled);
          Bar2 bar2 = (Bar2) map.get(1);
          String actual = bar2.x;
  
          assertEquals(expected, actual);
      }
  
      @Test
      public void test2e() {
          ChronicleMap<Integer, Bar> map = ChronicleMapBuilder.simpleMapOf(Integer.class, Bar.class)
                  .name("bar")
                  .averageValueSize(4096)
                  .entries(10)
                  .valueMarshaller(new CommonMarshallableReaderWriter(Bar.class))
                  .create();
  
          String expected = expected();
  
          Bar value = new Bar(expected);
          map.put(1, value);
          assertFalse(value.usesSelfDescribingMessage());
          assertFalse(value.writeMarshallableWireOutCalled);
          String actual = map.get(1).x;
  
          assertEquals(expected, actual);
      }
      @Test
      public void test2f() {
          ChronicleMap<Integer, Bar2> map = ChronicleMapBuilder.simpleMapOf(Integer.class, Bar2.class)
                  .name("bar")
                  .averageValueSize(1024)
                  .entries(10)
                  .valueMarshaller(new CommonMarshallableReaderWriter(Bar2.class))
                  .create();
  
          String expected = expected();
  
          Bar2 value = new Bar2(expected);
          map.put(1, value);
          assertTrue(value.usesSelfDescribingMessage());
          assertTrue(value.writeMarshallableWireOutCalled);
          String actual = map.get(1).x;
  
          assertEquals(expected, actual);
      }
  
      @NotNull
      private static String expected() {
          String expected = IntStream.range(0, 4096)
                  .mapToObj(i -> i % 50 == 0 ? String.format("\n%04d", i) : "" + i % 10)
                  .collect(Collectors.joining(""));
          return expected;
      }
  
      public static class Foo implements Serializable {
          public String x;
  
          Foo(int length) {
              this.x = "x" + IntStream.range(0, length)
                      .mapToObj(i -> "ä")
                      .collect(Collectors.joining(""));
          }
  
          public Foo(String expected) {
              x = expected;
          }
      }
  
      static class Bar extends BytesInBinaryMarshallable {
  
          final String x;
          transient boolean writeMarshallableWireOutCalled;
  
          public Bar(String expected) {
              this.x = expected;
          }
  
          @Override
          public void writeMarshallable(@NotNull WireOut wire) {
              this.writeMarshallableWireOutCalled = true;
              super.writeMarshallable(wire);
          }
  
          @Override
          public String toString() {
              return "Bar{" +
                      "x='" + x + '\'' +
                      ", writeMarshallableWireOutCalled=" + writeMarshallableWireOutCalled +
                      '}';
          }
      }
  
      static class Bar2 extends SelfDescribingMarshallable {
  
          final String x;
          transient boolean writeMarshallableWireOutCalled;
  
          public Bar2(String expected) {
              this.x = expected;
          }
  
          @Override
          public void writeMarshallable(@NotNull WireOut wire) {
              this.writeMarshallableWireOutCalled = true;
              super.writeMarshallable(wire);
          }
  
          @Override
          public String toString() {
              return "Bar2{" +
                      "x='" + x + '\'' +
                      ", writeMarshallableWireOutCalled=" + writeMarshallableWireOutCalled +
                      '}';
          }
      }
  }
  