title: How to avoid creating new instance of byteable data when using ChronicleMap.put
body: <p>I am learning how to use ChronicleMap 3.12 by using Byteable key and value classes. When I run my code with a loop of ChronicleMap.put operations based on the call stack it seems to create a value object everytime ChronicleMap.put is called. I would assume using Byteable value class will prevent object creation. Could someone tell me if I have potentially done something incorrectly?</p>
  
  <p>Code to create the ChronicleMap (both TestDataKeyForChronicleMap and TestDataForChronicleMap are Byteable):</p>
  
  <pre><code>    map = ChronicleMap.of( TestDataKeyForChronicleMap.class, TestDataForChronicleMap.class)
              .name( "TestDataMapForChronicleMap")
              .entries(aMaxNoOfRecords).
              .create();
  </code></pre>
  
  <p>The call stack when I am running the ChronicleMap.put</p>
  
  <pre><code>at sun.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
      at net.openhft.chronicle.core.util.ObjectUtils.lambda$null$0(ObjectUtils.java:71)
      at net.openhft.chronicle.core.util.ThrowingSupplier.lambda$asSupplier$0(ThrowingSupplier.java:42)
      at net.openhft.chronicle.core.util.ObjectUtils.newInstance(ObjectUtils.java:297)
      at net.openhft.chronicle.hash.serialization.impl.InstanceCreatingMarshaller.createInstance(InstanceCreatingMarshaller.java:67)
      at net.openhft.chronicle.hash.serialization.impl.ByteableSizedReader.read(ByteableSizedReader.java:42)
      at net.openhft.chronicle.hash.serialization.impl.ByteableSizedReader.read(ByteableSizedReader.java:31)
      at net.openhft.chronicle.map.impl.CompiledMapQueryContext$EntryValueBytesData.innerGetUsing(CompiledMapQueryContext.java:585)
      at net.openhft.chronicle.map.impl.CompiledMapQueryContext$EntryValueBytesData.getUsing(CompiledMapQueryContext.java:595)
      at net.openhft.chronicle.map.impl.CompiledMapQueryContext$DefaultReturnValue.initDefaultReturnedValue(CompiledMapQueryContext.java:411)
      at net.openhft.chronicle.map.impl.CompiledMapQueryContext$DefaultReturnValue.returnValue(CompiledMapQueryContext.java:400)
      at net.openhft.chronicle.map.MapMethods.put(MapMethods.java:86)
      at net.openhft.chronicle.map.VanillaChronicleMap.put(VanillaChronicleMap.java:716)
  </code></pre>
  
  <p>Thanks.</p>
  
  <p>Update to include TestDataKeyForChronicleMap:</p>
  
  <pre><code>import java.nio.BufferOverflowException;
  import java.nio.BufferUnderflowException;
  
  import net.openhft.chronicle.bytes.Byteable;
  import net.openhft.chronicle.bytes.BytesStore;
  
  public class TestDataKeyForChronicleMap implements Byteable
  {
      private final static long   MAX_SIZE = 16;
      private BytesStore bytesStore;
      private long offset;
  
      @Override
      public BytesStore bytesStore() 
      {
          return bytesStore;
      }
  
      @Override
      public void bytesStore(BytesStore aBytesStore, long anOffset, long aSize)
              throws IllegalStateException, IllegalArgumentException,
              BufferOverflowException, BufferUnderflowException 
      {
          if ( aSize != MAX_SIZE )
          {
              throw new IllegalArgumentException();
          }
          bytesStore = aBytesStore;
          offset = anOffset;
      }
  
      @Override
      public long maxSize() 
      {
          return MAX_SIZE;
      }
  
      @Override
      public long offset() 
      {
          return offset;
      }
  
      /**
       * set key
       * @param aKey1 key 1
       * @param aKey2 key 2
       */
      public void setKey( long aKey1, long aKey2 )
      {
          bytesStore.writeLong( offset, aKey1 );
          bytesStore.writeLong( offset + 8, aKey2 );
      }
  
      /**
       * get key 1
       * @return key 1
       */
      public long getKey1()
      {
          return bytesStore.readLong( offset );
      }
  
      /**
       * get key 2
       * @return key 2
       */
      public long getKey2()
      {
          return bytesStore.readLong( offset + 8 );
      }
  }
  </code></pre>
  
  <p>Code for TestDataForChronicleMap:</p>
  
  <pre><code>import java.nio.BufferOverflowException;
  import java.nio.BufferUnderflowException;
  
  import net.openhft.chronicle.bytes.Byteable;
  import net.openhft.chronicle.bytes.BytesStore;
  
  public final class TestDataForChronicleMap implements TestData, Byteable
  {
      private final static long   MAX_SIZE = 48;
      private BytesStore bytesStore;
      private long offset;
  
      public TestDataForChronicleMap()
      {
          Thread.currentThread().dumpStack();
      }
  
      @Override
      public BytesStore bytesStore() 
      {
          return bytesStore;
      }
  
      @Override
      public void bytesStore(BytesStore aBytesStore, long anOffset, long aSize)
              throws IllegalStateException, IllegalArgumentException,
              BufferOverflowException, BufferUnderflowException 
      {
          if ( aSize != MAX_SIZE )
          {
              throw new IllegalArgumentException();
          }
          bytesStore = aBytesStore;
          offset = anOffset;
      }
  
      @Override
      public long maxSize() 
      {
          return MAX_SIZE;
      }
  
      @Override
      public long offset() 
      {
          return offset;
      }
  
      @Override
      public void setKey(long aKey1, long aKey2) 
      {
          bytesStore.writeLong(offset+0, aKey1);
          bytesStore.writeLong(offset+8, aKey2);
          bytesStore.writeLong(offset+16, -1L);
          bytesStore.writeLong(offset+24, -1L);
          bytesStore.writeLong(offset+32, -1L);
          bytesStore.writeLong(offset+40, -1L);
      }
  
      @Override
      public void setData(long aKey1, long aKey2) 
      {
          bytesStore.writeLong(offset+0, aKey1);
          bytesStore.writeLong(offset+8, aKey2);
          bytesStore.writeLong(offset+16, aKey1);
          bytesStore.writeLong(offset+24, aKey2);
          bytesStore.writeLong(offset+32, aKey2);
          bytesStore.writeLong(offset+40, aKey1);
      }
  
      @Override
      public boolean isCorrect() 
      {
          return ( bytesStore.readLong(offset+0) ==  bytesStore.readLong(offset+16) &amp;&amp;  bytesStore.readLong(offset+0) ==  bytesStore.readLong(offset+40) ) 
                  &amp;&amp;
                  (  bytesStore.readLong(offset+8) ==  bytesStore.readLong(offset+24) &amp;&amp;  bytesStore.readLong(offset+8) ==  bytesStore.readLong(offset+32) );
      }
  
      @Override
      public long getKey1() 
      {
          return bytesStore.readLong(offset+0 );
      }
  
      @Override
      public long getKey2() 
      {
          return bytesStore.readLong(offset+8 );
      }
  
      @Override
      public String getPrintableText() 
      {
          StringBuilder builder = new StringBuilder();
          builder.append( bytesStore.readLong(offset+0) );
          builder.append( ' ' );
          builder.append( bytesStore.readLong(offset+8) );
          builder.append( ' ' );
          builder.append( bytesStore.readLong(offset+16) );
          builder.append( ' ' );
          builder.append( bytesStore.readLong(offset+24) );
          builder.append( ' ' );
          builder.append( bytesStore.readLong(offset+32) );
          builder.append( ' ' );
          builder.append( bytesStore.readLong(offset+40) );
          return builder.toString();
      }
  }
  </code></pre>
  
  <p>Code of the put loop:</p>
  
  <pre><code>/**
   * test add
   * @param aMap map to be used
   * @param aNoOfData no of data to be used for testing
   * @return time taken in ms
   */
  public final static long TestAdd( final TestDataMap aMap, final long aNoOfData )
  {
      long time = System.currentTimeMillis();
      TestData data = aMap.createTestData();
      for( long count=0; count&lt;aNoOfData; count++ )
      {
          data.setData( count, count+aNoOfData);
          aMap.put(data);
      }
      return System.currentTimeMillis() - time;
  }
  </code></pre>
  
  <p>Interface for TestDataMap</p>
  
  <pre><code>public interface TestDataMap 
  {
      /**
       * create test data
       */
      public TestData createTestData();
  
      /**
       * create test data for zero copy
       */
      public TestData createTestDataForZeroCopy();
  
      /**
       * check if map requires new data in each entry
       * @return true if new data is needed for each entry or false if data can be reused
       */
      public boolean needNewData();
  
      /**
       * put test data into the map
       * @param aData
       */
      public void put( TestData aData );
  
      /**
       * get test data from the map
       */
      public TestData get( TestData aData );
  
      /**
       * get test data from the map with zero copy
       */
      public boolean getZeroCopy( TestData aData );
  
      /**
       * remove the test data from the map
       */
      public boolean remove( TestData aData );
  
      /**
       * get if the map contains the test data
       */
      public boolean contains( TestData aData );
  
      /**
       * get size
       */
      public long getSize();
  
      /**
       * clear the map
       */
      public void clear();
  
      /**
       * dispose
       */
      public void dispose();
  }
  </code></pre>
  
  <p>And the TestDataMapForChronicleMap</p>
  
  <pre><code>import java.io.IOException;
  
  import net.openhft.chronicle.bytes.BytesStore;
  import net.openhft.chronicle.map.ChronicleMap;
  
  public final class TestDataMapForChronicleMap implements TestDataMap
  {
      private ChronicleMap&lt;TestDataKeyForChronicleMap,TestDataForChronicleMap&gt; map;
      private TestDataKeyForChronicleMap key = new TestDataKeyForChronicleMap();
  
      public TestDataMapForChronicleMap( long aMaxNoOfRecords ) throws IOException
      {
          map = ChronicleMap.of( TestDataKeyForChronicleMap.class, TestDataForChronicleMap.class)
                  .name( "TestDataMapForChronicleMap")
                  .entries(aMaxNoOfRecords)
                  .putReturnsNull( true )
                  .create();
          BytesStore bytesStore = BytesStore.wrap( new byte[16] );
          key.bytesStore( bytesStore, 0, bytesStore.capacity() );
      }
  
      /**
       * put test data into the map
       * @param aData
       */
      public void put( final TestData aData )
      {
          key.setKey( aData.getKey1(), aData.getKey2() );
          map.put( key, (TestDataForChronicleMap)aData );
      }
  
      /**
       * get test data from the map
       */
      public TestData get( final TestData aData )
      {
          key.setKey( aData.getKey1(), aData.getKey2() );
          return map.getUsing( key, (TestDataForChronicleMap)aData ); 
      }
  
  
  
  /**
       * remove the test data from the map
       */
      public boolean remove( final TestData aData )
      {
          key.setKey( aData.getKey1(), aData.getKey2() );
          return map.remove( key ) != null;
      }
  
      /**
       * get if the map contains the test data
       */
      public boolean contains( final TestData aData )
      {
          key.setKey( aData.getKey1(), aData.getKey2() );
          return map.containsKey( key );
      }
  
      /**
       * dispose the map and releases all the resources
       * @param shouldRemoveFiles true will remove all the existing memory mapped files from the system
       */
      public void dispose( final boolean shouldRemoveFiles )
      {
          map.close();
      }
  
      /**
       * get size
       * @return size of the map
       */
      public long getSize()
      {
          return map.size();
      }
  
      /**
       * clear all the values from the map
       */
      public void clear()
      {
          map.clear();
      }
  
      @Override
      public boolean getZeroCopy(final TestData aData ) 
      {
          key.setKey( aData.getKey1(), aData.getKey2() );
          return map.getUsing( key, (TestDataForChronicleMap)aData ) != null; 
      }
  
      @Override
      public TestData createTestData() 
      {
          TestDataForChronicleMap data = new TestDataForChronicleMap();
          BytesStore bytesStore = BytesStore.wrap( new byte[48] );
          data.bytesStore( bytesStore, 0, bytesStore.capacity() );
          return data;
      }
  
      @Override
      public TestData createTestDataForZeroCopy()
      {
          //return createTestData();
          return null;
      }
  
      @Override
      public boolean needNewData() 
      {
          return false;
      }
  
      @Override
      public void dispose() 
      {
          map.close();
      }
  
      /**
       * get heap memory
       */
      public long getOffHeapMemory()
      {
          return map.offHeapMemoryUsed();
      }
  }
  </code></pre>
  
  <p>TestData code</p>
  
  <pre><code>/**
   * TestData has the following layout
   * long key1
   * long key2
   * long value1 (value = key1)
   * long value2 (value = key2)
   * long value3 (value = key2)
   * long value4 (value = key1)
   */
  public interface TestData 
  {
      /**
       * set key
       * @param aKey1 key 1
       * @param aKey2 key 2
       */
      public void setKey( long aKey1, long aKey2 );
  
      /**
       * set data
       * @param aKey1 key 1
       * @param aKey2 key 2
       */
      public void setData( long aKey1, long aKey2 );
  
      /**
       * check if the data is correct
       */
      public boolean isCorrect();
  
      /**
       * get key 1
       * @return key 1
       */
      public long getKey1();
  
      /**
       * get key 2
       * @return key 2
       */
      public long getKey2();
  
      /**
       * to string
       */
      public String getPrintableText();
  }
  </code></pre>