You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by do...@apache.org on 2021/05/14 14:48:13 UTC

[geode] branch develop updated: GEODE-9221: Remove uses of ByteArrayWrapper from RedisString (#6464)

This is an automated email from the ASF dual-hosted git repository.

donalevans pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new cbda688  GEODE-9221: Remove uses of ByteArrayWrapper from RedisString (#6464)
cbda688 is described below

commit cbda688f15c2e6a270a2f6041a70d648d58aa748
Author: Donal Evans <do...@vmware.com>
AuthorDate: Fri May 14 07:47:12 2021 -0700

    GEODE-9221: Remove uses of ByteArrayWrapper from RedisString (#6464)
    
     - Replace uses of ByteArrayWrapper in RedisString and NullRedisString
     with byte[]
     - Remove unused methods from ByteArrayWrapper
     - Populate RedisString.bitcountTable at initialization time via static method
     - Added integration tests for RedisString.bitpos
     - Refactor to remove warnings
    
    Authored-by: Donal Evans <do...@vmware.com>
---
 .../hash/MemoryOverheadIntegrationTest.java        |   2 +-
 .../string/AbstractBitPosIntegrationTest.java      |  57 +++
 .../codeAnalysis/sanctionedDataSerializables.txt   |   4 +-
 .../redis/internal/data/ByteArrayWrapper.java      |  14 -
 .../geode/redis/internal/data/CommandHelper.java   |   2 +-
 .../geode/redis/internal/data/NullRedisString.java |  77 ++--
 .../geode/redis/internal/data/RedisString.java     | 413 ++++-----------------
 .../data/RedisStringCommandsFunctionExecutor.java  |  40 +-
 .../redis/internal/executor/CommandFunction.java   |   6 +-
 .../internal/executor/string/AppendExecutor.java   |   7 +-
 .../internal/executor/string/GetExecutor.java      |   6 +-
 .../internal/executor/string/GetRangeExecutor.java |   5 +-
 .../internal/executor/string/GetSetExecutor.java   |   4 +-
 .../internal/executor/string/MGetExecutor.java     |   3 +-
 .../internal/executor/string/MSetExecutor.java     |   4 +-
 .../internal/executor/string/MSetNXExecutor.java   |   4 +-
 .../executor/string/RedisStringCommands.java       |  13 +-
 .../string/RedisStringCommandsFunctionInvoker.java |  13 +-
 .../internal/executor/string/SetEXExecutor.java    |   3 +-
 .../internal/executor/string/SetExecutor.java      |  17 +-
 .../internal/executor/string/SetNXExecutor.java    |   4 +-
 .../redis/internal/executor/string/SetOptions.java |   5 +-
 .../apache/geode/redis/internal/netty/Coder.java   |  20 +-
 .../geode/redis/internal/data/RedisStringTest.java | 360 ++++++++----------
 24 files changed, 391 insertions(+), 692 deletions(-)

diff --git a/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/MemoryOverheadIntegrationTest.java b/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/MemoryOverheadIntegrationTest.java
index f22c242..eae64bb 100755
--- a/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/MemoryOverheadIntegrationTest.java
+++ b/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/MemoryOverheadIntegrationTest.java
@@ -53,7 +53,7 @@ public class MemoryOverheadIntegrationTest extends AbstractMemoryOverheadIntegra
   @Override
   EnumMap<Measurement, Integer> expectedPerEntryOverhead() {
     EnumMap<Measurement, Integer> result = new EnumMap<>(Measurement.class);
-    result.put(Measurement.STRING, 201);
+    result.put(Measurement.STRING, 185);
     result.put(Measurement.SET, 386);
     result.put(Measurement.SET_ENTRY, 72);
     result.put(Measurement.HASH, 490);
diff --git a/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/string/AbstractBitPosIntegrationTest.java b/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/string/AbstractBitPosIntegrationTest.java
index e1a498b..c0c468f 100755
--- a/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/string/AbstractBitPosIntegrationTest.java
+++ b/geode-apis-compatible-with-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/string/AbstractBitPosIntegrationTest.java
@@ -76,6 +76,14 @@ public abstract class AbstractBitPosIntegrationTest implements RedisIntegrationT
   }
 
   @Test
+  public void bitpos_givenStartGreaterThanEnd() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {1, 1, 1, 1, 1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(3, 2))).isEqualTo(-1);
+  }
+
+  @Test
   public void bitpos_givenBitInFirstByte() {
     byte[] key = {1, 2, 3};
     byte[] bytes = {1, 1, 1, 1, 1};
@@ -116,10 +124,59 @@ public abstract class AbstractBitPosIntegrationTest implements RedisIntegrationT
   }
 
   @Test
+  public void bitposWithStartAndEnd_givenStartAndEndEqual() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {1, 1, 1, 1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(2, 2))).isEqualTo(7 + 2 * 8);
+  }
+
+  @Test
+  public void bitposWithStartAndEnd_givenStartAndEndNegative() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {1, 1, 1, 1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(-2, -1))).isEqualTo(7 + 2 * 8);
+  }
+
+  @Test
+  public void bitposWithStartAndEnd_givenEndGreaterThanOrEqualToByteArrayLength() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {1, 1, 1, 1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(0, bytes.length))).isEqualTo(7);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(0, bytes.length + 1))).isEqualTo(7);
+  }
+
+  @Test
   public void bitposWithStartAndEnd_givenNoBits() {
     byte[] key = {1, 2, 3};
     byte[] bytes = {1, 0, 0, 1};
     jedis.set(key, bytes);
     assertThat(jedis.bitpos(key, true, new BitPosParams(1, 2))).isEqualTo(-1);
   }
+
+  @Test
+  public void bitposWithStart_givenStartMoreNegativeThanByteArrayLength() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {1, 1, 1, 1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, true, new BitPosParams(-(bytes.length + 1)))).isEqualTo(7);
+  }
+
+  @Test
+  public void bitposFalseWithStartAndEnd_givenEndGreaterThanByteArrayLengthAndNoBitFound() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {-1, -1, -1, -1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, false, new BitPosParams(0, bytes.length))).isEqualTo(-1);
+  }
+
+  @Test
+  public void bitposFalseWithStart_givenNoBitFound() {
+    byte[] key = {1, 2, 3};
+    byte[] bytes = {-1, -1, -1, -1};
+    jedis.set(key, bytes);
+    assertThat(jedis.bitpos(key, false, new BitPosParams(0))).isEqualTo(bytes.length * 8);
+  }
 }
diff --git a/geode-apis-compatible-with-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-apis-compatible-with-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index c97c184..38b06fc 100644
--- a/geode-apis-compatible-with-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-apis-compatible-with-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -23,8 +23,8 @@ toData,26
 fromData,26
 
 org/apache/geode/redis/internal/data/RedisString,2
-toData,26
-fromData,30
+toData,23
+fromData,23
 
 org/apache/geode/redis/internal/executor/string/SetOptions,2
 fromData,34
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
index 79d4f4f..046914a 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
@@ -147,20 +147,6 @@ public class ByteArrayWrapper
     return 0;
   }
 
-
-  private static byte[] concatArrays(byte[] o, byte[] n) {
-    int oLen = o.length;
-    int nLen = n.length;
-    byte[] combined = new byte[oLen + nLen];
-    System.arraycopy(o, 0, combined, 0, oLen);
-    System.arraycopy(n, 0, combined, oLen, nLen);
-    return combined;
-  }
-
-  public void append(byte[] appendBytes) {
-    setBytes(concatArrays(value, appendBytes));
-  }
-
   @Override
   public int getDSFID() {
     return DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER;
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/CommandHelper.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/CommandHelper.java
index e78c963..2e7c524 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/CommandHelper.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/CommandHelper.java
@@ -166,7 +166,7 @@ public class CommandHelper {
     return checkStringType(redisData, true);
   }
 
-  RedisString setRedisString(RedisKey key, ByteArrayWrapper value) {
+  RedisString setRedisString(RedisKey key, byte[] value) {
     RedisString result;
     RedisData redisData = getRedisData(key);
 
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisString.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisString.java
index 684778a..31a9c85 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisString.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisString.java
@@ -38,7 +38,7 @@ import org.apache.geode.redis.internal.netty.Coder;
  */
 public class NullRedisString extends RedisString {
   public NullRedisString() {
-    super(new ByteArrayWrapper(new byte[0]));
+    super(new byte[0]);
   }
 
   @Override
@@ -52,23 +52,17 @@ public class NullRedisString extends RedisString {
   }
 
   @Override
-  protected void valueSet(ByteArrayWrapper newValue) {
+  protected void valueSet(byte[] bytes) {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  protected void valueSetBytes(byte[] bytes) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public ByteArrayWrapper get() {
+  public byte[] get() {
     return null;
   }
 
   @Override
-  public int bitpos(Region<RedisKey, RedisData> region, RedisKey key, int bit,
-      int start, Integer end) {
+  public int bitpos(int bit, int start, Integer end) {
     if (bit == 0) {
       return 0;
     } else {
@@ -83,10 +77,10 @@ public class NullRedisString extends RedisString {
     if (bitValue == 1) {
       byte[] bytes = new byte[byteIndex + 1];
       bytes[byteIndex] = (byte) (0x80 >> bitIndex);
-      newValue = new RedisString(new ByteArrayWrapper(bytes));
+      newValue = new RedisString(bytes);
     } else {
       // all bits are 0 so use an empty byte array
-      newValue = new RedisString(new ByteArrayWrapper(new byte[0]));
+      newValue = new RedisString(new byte[0]);
     }
     region.put(key, newValue);
     return 0;
@@ -96,7 +90,7 @@ public class NullRedisString extends RedisString {
   public long incr(Region<RedisKey, RedisData> region, RedisKey key)
       throws NumberFormatException, ArithmeticException {
     byte[] newValue = {Coder.NUMBER_1_BYTE};
-    region.put(key, new RedisString(new ByteArrayWrapper(newValue)));
+    region.put(key, new RedisString(newValue));
     return 1;
   }
 
@@ -104,7 +98,7 @@ public class NullRedisString extends RedisString {
   public long incrby(Region<RedisKey, RedisData> region, RedisKey key,
       long increment) throws NumberFormatException, ArithmeticException {
     byte[] newValue = Coder.longToBytes(increment);
-    region.put(key, new RedisString(new ByteArrayWrapper(newValue)));
+    region.put(key, new RedisString(newValue));
     return increment;
   }
 
@@ -112,34 +106,32 @@ public class NullRedisString extends RedisString {
   public BigDecimal incrbyfloat(Region<RedisKey, RedisData> region, RedisKey key,
       BigDecimal increment) throws NumberFormatException, ArithmeticException {
     byte[] newValue = Coder.bigDecimalToBytes(increment);
-    region.put(key, new RedisString(new ByteArrayWrapper(newValue)));
+    region.put(key, new RedisString(newValue));
     return increment;
   }
 
   @Override
   public long decr(Region<RedisKey, RedisData> region, RedisKey key)
       throws NumberFormatException, ArithmeticException {
-    region.put(key, new RedisString(new ByteArrayWrapper(Coder.stringToBytes("-1"))));
+    region.put(key, new RedisString(Coder.stringToBytes("-1")));
     return -1;
   }
 
   @Override
   public long decrby(Region<RedisKey, RedisData> region, RedisKey key, long decrement) {
     byte[] newValue = Coder.longToBytes(-decrement);
-    region.put(key, new RedisString(new ByteArrayWrapper(newValue)));
+    region.put(key, new RedisString(newValue));
     return -decrement;
   }
 
   @Override
-  public int append(ByteArrayWrapper appendValue, Region<RedisKey, RedisData> region,
-      RedisKey key) {
+  public int append(Region<RedisKey, RedisData> region, RedisKey key, byte[] appendValue) {
     region.put(key, new RedisString(appendValue));
-    return appendValue.length();
+    return appendValue.length;
   }
 
   @Override
-  public ByteArrayWrapper getset(Region<RedisKey, RedisData> region, RedisKey key,
-      ByteArrayWrapper value) {
+  public byte[] getset(Region<RedisKey, RedisData> region, RedisKey key, byte[] value) {
     region.put(key, new RedisString(value));
     return null;
   }
@@ -153,7 +145,7 @@ public class NullRedisString extends RedisString {
         newBytes = new byte[offset + valueToAdd.length];
         System.arraycopy(valueToAdd, 0, newBytes, offset, valueToAdd.length);
       }
-      region.put(key, new RedisString(new ByteArrayWrapper(newBytes)));
+      region.put(key, new RedisString(newBytes));
     }
     return newBytes.length;
   }
@@ -162,8 +154,7 @@ public class NullRedisString extends RedisString {
    * SET is currently mostly implemented here. It does not have an implementation on
    * RedisString which is a bit odd.
    */
-  public boolean set(CommandHelper helper, RedisKey key, ByteArrayWrapper value,
-      SetOptions options) {
+  public boolean set(CommandHelper helper, RedisKey key, byte[] value, SetOptions options) {
     if (options != null) {
       if (options.isNX()) {
         return setnx(helper, key, value, options);
@@ -179,8 +170,7 @@ public class NullRedisString extends RedisString {
     return true;
   }
 
-  private boolean setnx(CommandHelper helper, RedisKey key, ByteArrayWrapper value,
-      SetOptions options) {
+  private boolean setnx(CommandHelper helper, RedisKey key, byte[] value, SetOptions options) {
     if (helper.getRedisData(key).exists()) {
       return false;
     }
@@ -196,7 +186,7 @@ public class NullRedisString extends RedisString {
    * that care if a RedisString for "key" exists.
    */
   public int bitop(CommandHelper helper, String operation, RedisKey key, List<RedisKey> sources) {
-    List<ByteArrayWrapper> sourceValues = new ArrayList<>();
+    List<byte[]> sourceValues = new ArrayList<>();
     int selfIndex = -1;
     // Read all the source values, except for self, before locking the stripe.
     RedisStringCommands commander =
@@ -221,7 +211,7 @@ public class NullRedisString extends RedisString {
   }
 
   private int doBitOp(CommandHelper helper, String operation, RedisKey key, int selfIndex,
-      List<ByteArrayWrapper> sourceValues) {
+      List<byte[]> sourceValues) {
     if (selfIndex != -1) {
       RedisString redisString = helper.getRedisString(key, true);
       if (!redisString.isNull()) {
@@ -229,12 +219,12 @@ public class NullRedisString extends RedisString {
       }
     }
     int maxLength = 0;
-    for (ByteArrayWrapper sourceValue : sourceValues) {
-      if (sourceValue != null && maxLength < sourceValue.length()) {
-        maxLength = sourceValue.length();
+    for (byte[] sourceValue : sourceValues) {
+      if (sourceValue != null && maxLength < sourceValue.length) {
+        maxLength = sourceValue.length;
       }
     }
-    ByteArrayWrapper newValue;
+    byte[] newValue;
     switch (operation) {
       case "AND":
         newValue = doBitOp(BitOp.AND, sourceValues, maxLength);
@@ -249,23 +239,23 @@ public class NullRedisString extends RedisString {
         newValue = not(sourceValues.get(0), maxLength);
         break;
     }
-    if (newValue.length() == 0) {
+    if (newValue.length == 0) {
       helper.getRegion().remove(key);
     } else {
       helper.setRedisString(key, newValue);
     }
-    return newValue.length();
+    return newValue.length;
   }
 
-  private ByteArrayWrapper doBitOp(BitOp bitOp, List<ByteArrayWrapper> sourceValues, int max) {
+  private byte[] doBitOp(BitOp bitOp, List<byte[]> sourceValues, int max) {
     byte[] dest = new byte[max];
     for (int i = 0; i < max; i++) {
       byte b = 0;
       boolean firstByte = true;
-      for (ByteArrayWrapper sourceValue : sourceValues) {
+      for (byte[] sourceValue : sourceValues) {
         byte sourceByte = 0;
-        if (sourceValue != null && i < sourceValue.length()) {
-          sourceByte = sourceValue.toBytes()[i];
+        if (sourceValue != null && i < sourceValue.length) {
+          sourceByte = sourceValue[i];
         }
         if (firstByte) {
           b = sourceByte;
@@ -286,22 +276,21 @@ public class NullRedisString extends RedisString {
       }
       dest[i] = b;
     }
-    return new ByteArrayWrapper(dest);
+    return dest;
   }
 
-  private ByteArrayWrapper not(ByteArrayWrapper sourceValue, int max) {
+  private byte[] not(byte[] sourceValue, int max) {
     byte[] dest = new byte[max];
     if (sourceValue == null) {
       for (int i = 0; i < max; i++) {
         dest[i] = ~0;
       }
     } else {
-      byte[] cA = sourceValue.toBytes();
       for (int i = 0; i < max; i++) {
-        dest[i] = (byte) (~cA[i] & 0xFF);
+        dest[i] = (byte) (~sourceValue[i] & 0xFF);
       }
     }
-    return new ByteArrayWrapper(dest);
+    return dest;
   }
 
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
index df04cdb..c3475ae 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
@@ -37,34 +37,36 @@ import org.apache.geode.redis.internal.netty.Coder;
 public class RedisString extends AbstractRedisData {
   private int appendSequence;
 
-  private ByteArrayWrapper value;
+  private byte[] value;
 
   // this value is empirically derived using ReflectionObjectSizer, which provides an exact size
   // of the object. It can't be used directly because of its performance impact. This value causes
   // the size we keep track of to converge to the actual size as it increases.
-  protected static final int BASE_REDIS_STRING_OVERHEAD = 64;
+  protected static final int BASE_REDIS_STRING_OVERHEAD = 48;
 
-  public RedisString(ByteArrayWrapper value) {
+  // An array containing the number of set bits for each value from 0x00 to 0xff
+  private static final byte[] bitCountTable = getBitCountTable();
+
+  public RedisString(byte[] value) {
     this.value = value;
   }
 
   // for serialization
   public RedisString() {}
 
-  public ByteArrayWrapper get() {
-    return new ByteArrayWrapper(value.toBytes());
+  public byte[] get() {
+    return value;
   }
 
-  public void set(ByteArrayWrapper value) {
-    valueSet(value);
+  public void set(byte[] value) {
+    this.value = value;
   }
 
-  public int append(ByteArrayWrapper appendValue, Region<RedisKey, RedisData> region,
-      RedisKey key) {
-    valueAppend(appendValue.toBytes());
+  public int append(Region<RedisKey, RedisData> region, RedisKey key, byte[] appendValue) {
+    valueAppend(appendValue);
     appendSequence++;
-    storeChanges(region, key, new AppendDeltaInfo(appendValue.toBytes(), appendSequence));
-    return value.length();
+    storeChanges(region, key, new AppendDeltaInfo(appendValue, appendSequence));
+    return value.length;
   }
 
   public long incr(Region<RedisKey, RedisData> region, RedisKey key)
@@ -74,7 +76,7 @@ public class RedisString extends AbstractRedisData {
       throw new ArithmeticException(RedisConstants.ERROR_OVERFLOW);
     }
     longValue++;
-    valueSetBytes(Coder.longToBytes(longValue));
+    value = Coder.longToBytes(longValue);
     // numeric strings are short so no need to use delta
     region.put(key, this);
     return longValue;
@@ -87,7 +89,7 @@ public class RedisString extends AbstractRedisData {
       throw new ArithmeticException(RedisConstants.ERROR_OVERFLOW);
     }
     longValue += increment;
-    valueSetBytes(Coder.longToBytes(longValue));
+    value = Coder.longToBytes(longValue);
     // numeric strings are short so no need to use delta
     region.put(key, this);
     return longValue;
@@ -98,7 +100,7 @@ public class RedisString extends AbstractRedisData {
       throws NumberFormatException, ArithmeticException {
     BigDecimal bigDecimalValue = parseValueAsBigDecimal();
     bigDecimalValue = bigDecimalValue.add(increment);
-    valueSetBytes(Coder.bigDecimalToBytes(bigDecimalValue));
+    value = Coder.bigDecimalToBytes(bigDecimalValue);
 
     // numeric strings are short so no need to use delta
     region.put(key, this);
@@ -111,7 +113,7 @@ public class RedisString extends AbstractRedisData {
       throw new ArithmeticException(RedisConstants.ERROR_OVERFLOW);
     }
     longValue -= decrement;
-    valueSetBytes(Coder.longToBytes(longValue));
+    value = Coder.longToBytes(longValue);
     // numeric strings are short so no need to use delta
     region.put(key, this);
     return longValue;
@@ -124,7 +126,7 @@ public class RedisString extends AbstractRedisData {
       throw new ArithmeticException(RedisConstants.ERROR_OVERFLOW);
     }
     longValue--;
-    valueSetBytes(Coder.longToBytes(longValue));
+    value = Coder.longToBytes(longValue);
     // numeric strings are short so no need to use delta
     region.put(key, this);
     return longValue;
@@ -132,14 +134,14 @@ public class RedisString extends AbstractRedisData {
 
   private long parseValueAsLong() {
     try {
-      return Long.parseLong(value.toString());
+      return Coder.bytesToLong(value);
     } catch (NumberFormatException ex) {
       throw new NumberFormatException(RedisConstants.ERROR_NOT_INTEGER);
     }
   }
 
   private BigDecimal parseValueAsBigDecimal() {
-    String valueString = value.toString();
+    String valueString = Coder.bytesToString(value);
     if (valueString.contains(" ")) {
       throw new NumberFormatException(RedisConstants.ERROR_NOT_A_VALID_FLOAT);
     }
@@ -150,44 +152,39 @@ public class RedisString extends AbstractRedisData {
     }
   }
 
-  public ByteArrayWrapper getrange(long start, long end) {
-    int length = value.length();
+  public byte[] getrange(long start, long end) {
+    int length = value.length;
     int boundedStart = getBoundedStartIndex(start, length);
     int boundedEnd = getBoundedEndIndex(end, length);
 
-    /*
-     * Can't 'start' at end of value
-     */
+    // Can't 'start' at end of value
     if (boundedStart > boundedEnd || boundedStart == length) {
-      return new ByteArrayWrapper(new byte[0]);
+      return new byte[0];
     }
-    /*
-     * 1 is added to end because the end in copyOfRange is exclusive but in Redis it is inclusive
-     */
+    // 1 is added to end because the end in copyOfRange is exclusive but in Redis it is inclusive
     if (boundedEnd != length) {
       boundedEnd++;
     }
-    byte[] returnRange = Arrays.copyOfRange(value.toBytes(), boundedStart, boundedEnd);
-    return new ByteArrayWrapper(returnRange);
+    return Arrays.copyOfRange(value, boundedStart, boundedEnd);
   }
 
   public int setrange(Region<RedisKey, RedisData> region, RedisKey key, int offset,
       byte[] valueToAdd) {
     if (valueToAdd.length == 0) {
-      return value.length();
+      return value.length;
     }
     int totalLength = offset + valueToAdd.length;
-    byte[] bytes = value.toBytes();
+    byte[] bytes = value;
     if (totalLength < bytes.length) {
       System.arraycopy(valueToAdd, 0, bytes, offset, valueToAdd.length);
     } else {
       byte[] newBytes = Arrays.copyOf(bytes, totalLength);
       System.arraycopy(valueToAdd, 0, newBytes, offset, valueToAdd.length);
-      valueSetBytes(newBytes);
+      value = newBytes;
     }
     // TODO add delta support
     region.put(key, this);
-    return value.length();
+    return value.length;
   }
 
   private int getBoundedStartIndex(long index, int size) {
@@ -206,9 +203,8 @@ public class RedisString extends AbstractRedisData {
     }
   }
 
-  public int bitpos(Region<RedisKey, RedisData> region, RedisKey key, int bit,
-      int start, Integer end) {
-    int length = value.length();
+  public int bitpos(int bit, int start, Integer end) {
+    int length = value.length;
     if (length == 0) {
       return -1;
     }
@@ -216,6 +212,8 @@ public class RedisString extends AbstractRedisData {
     if (!endSet) {
       end = length - 1;
     }
+
+    // BITPOS allows indexing from the end of the string using negative values for start and end
     if (start < 0) {
       start += length;
     }
@@ -230,10 +228,10 @@ public class RedisString extends AbstractRedisData {
       end = 0;
     }
 
-    if (start > length) {
+    if (start >= length) {
       start = length - 1;
     }
-    if (end > length) {
+    if (end >= length) {
       end = length - 1;
     }
 
@@ -241,10 +239,9 @@ public class RedisString extends AbstractRedisData {
       return -1;
     }
 
-    byte[] bytes = value.toBytes();
     for (int i = start; i <= end; i++) {
       int cBit;
-      byte cByte = bytes[i];
+      byte cByte = value[i];
       for (int j = 0; j < 8; j++) {
         cBit = (cByte & (0x80 >> j)) >> (7 - j);
         if (cBit == bit) {
@@ -260,13 +257,12 @@ public class RedisString extends AbstractRedisData {
     return -1;
   }
 
-
   public long bitcount(int start, int end) {
     if (start < 0) {
-      start += value.length();
+      start += value.length;
     }
     if (end < 0) {
-      end += value.length();
+      end += value.length;
     }
 
     if (start < 0) {
@@ -276,312 +272,52 @@ public class RedisString extends AbstractRedisData {
       end = 0;
     }
 
-    if (end > value.length() - 1) {
-      end = value.length() - 1;
+    if (end > value.length - 1) {
+      end = value.length - 1;
     }
 
-    if (end < start || start >= value.length()) {
+    if (end < start) {
       return 0;
     }
 
     long setBits = 0;
     for (int j = start; j <= end; j++) {
-      setBits += bitcountTable[0xFF & value.toBytes()[j]];
+      setBits += bitCountTable[0xFF & value[j]];
     }
     return setBits;
   }
 
   public long bitcount() {
-    return bitcount(0, value.length() - 1);
-  }
-
-  private static final byte[] bitcountTable = {
-      0, // 0x0
-      1, // 0x1
-      1, // 0x2
-      2, // 0x3
-      1, // 0x4
-      2, // 0x5
-      2, // 0x6
-      3, // 0x7
-      1, // 0x8
-      2, // 0x9
-      2, // 0xa
-      3, // 0xb
-      2, // 0xc
-      3, // 0xd
-      3, // 0xe
-      4, // 0xf
-      1, // 0x10
-      2, // 0x11
-      2, // 0x12
-      3, // 0x13
-      2, // 0x14
-      3, // 0x15
-      3, // 0x16
-      4, // 0x17
-      2, // 0x18
-      3, // 0x19
-      3, // 0x1a
-      4, // 0x1b
-      3, // 0x1c
-      4, // 0x1d
-      4, // 0x1e
-      5, // 0x1f
-      1, // 0x20
-      2, // 0x21
-      2, // 0x22
-      3, // 0x23
-      2, // 0x24
-      3, // 0x25
-      3, // 0x26
-      4, // 0x27
-      2, // 0x28
-      3, // 0x29
-      3, // 0x2a
-      4, // 0x2b
-      3, // 0x2c
-      4, // 0x2d
-      4, // 0x2e
-      5, // 0x2f
-      2, // 0x30
-      3, // 0x31
-      3, // 0x32
-      4, // 0x33
-      3, // 0x34
-      4, // 0x35
-      4, // 0x36
-      5, // 0x37
-      3, // 0x38
-      4, // 0x39
-      4, // 0x3a
-      5, // 0x3b
-      4, // 0x3c
-      5, // 0x3d
-      5, // 0x3e
-      6, // 0x3f
-      1, // 0x40
-      2, // 0x41
-      2, // 0x42
-      3, // 0x43
-      2, // 0x44
-      3, // 0x45
-      3, // 0x46
-      4, // 0x47
-      2, // 0x48
-      3, // 0x49
-      3, // 0x4a
-      4, // 0x4b
-      3, // 0x4c
-      4, // 0x4d
-      4, // 0x4e
-      5, // 0x4f
-      2, // 0x50
-      3, // 0x51
-      3, // 0x52
-      4, // 0x53
-      3, // 0x54
-      4, // 0x55
-      4, // 0x56
-      5, // 0x57
-      3, // 0x58
-      4, // 0x59
-      4, // 0x5a
-      5, // 0x5b
-      4, // 0x5c
-      5, // 0x5d
-      5, // 0x5e
-      6, // 0x5f
-      2, // 0x60
-      3, // 0x61
-      3, // 0x62
-      4, // 0x63
-      3, // 0x64
-      4, // 0x65
-      4, // 0x66
-      5, // 0x67
-      3, // 0x68
-      4, // 0x69
-      4, // 0x6a
-      5, // 0x6b
-      4, // 0x6c
-      5, // 0x6d
-      5, // 0x6e
-      6, // 0x6f
-      3, // 0x70
-      4, // 0x71
-      4, // 0x72
-      5, // 0x73
-      4, // 0x74
-      5, // 0x75
-      5, // 0x76
-      6, // 0x77
-      4, // 0x78
-      5, // 0x79
-      5, // 0x7a
-      6, // 0x7b
-      5, // 0x7c
-      6, // 0x7d
-      6, // 0x7e
-      7, // 0x7f
-      1, // 0x80
-      2, // 0x81
-      2, // 0x82
-      3, // 0x83
-      2, // 0x84
-      3, // 0x85
-      3, // 0x86
-      4, // 0x87
-      2, // 0x88
-      3, // 0x89
-      3, // 0x8a
-      4, // 0x8b
-      3, // 0x8c
-      4, // 0x8d
-      4, // 0x8e
-      5, // 0x8f
-      2, // 0x90
-      3, // 0x91
-      3, // 0x92
-      4, // 0x93
-      3, // 0x94
-      4, // 0x95
-      4, // 0x96
-      5, // 0x97
-      3, // 0x98
-      4, // 0x99
-      4, // 0x9a
-      5, // 0x9b
-      4, // 0x9c
-      5, // 0x9d
-      5, // 0x9e
-      6, // 0x9f
-      2, // 0xa0
-      3, // 0xa1
-      3, // 0xa2
-      4, // 0xa3
-      3, // 0xa4
-      4, // 0xa5
-      4, // 0xa6
-      5, // 0xa7
-      3, // 0xa8
-      4, // 0xa9
-      4, // 0xaa
-      5, // 0xab
-      4, // 0xac
-      5, // 0xad
-      5, // 0xae
-      6, // 0xaf
-      3, // 0xb0
-      4, // 0xb1
-      4, // 0xb2
-      5, // 0xb3
-      4, // 0xb4
-      5, // 0xb5
-      5, // 0xb6
-      6, // 0xb7
-      4, // 0xb8
-      5, // 0xb9
-      5, // 0xba
-      6, // 0xbb
-      5, // 0xbc
-      6, // 0xbd
-      6, // 0xbe
-      7, // 0xbf
-      2, // 0xc0
-      3, // 0xc1
-      3, // 0xc2
-      4, // 0xc3
-      3, // 0xc4
-      4, // 0xc5
-      4, // 0xc6
-      5, // 0xc7
-      3, // 0xc8
-      4, // 0xc9
-      4, // 0xca
-      5, // 0xcb
-      4, // 0xcc
-      5, // 0xcd
-      5, // 0xce
-      6, // 0xcf
-      3, // 0xd0
-      4, // 0xd1
-      4, // 0xd2
-      5, // 0xd3
-      4, // 0xd4
-      5, // 0xd5
-      5, // 0xd6
-      6, // 0xd7
-      4, // 0xd8
-      5, // 0xd9
-      5, // 0xda
-      6, // 0xdb
-      5, // 0xdc
-      6, // 0xdd
-      6, // 0xde
-      7, // 0xdf
-      3, // 0xe0
-      4, // 0xe1
-      4, // 0xe2
-      5, // 0xe3
-      4, // 0xe4
-      5, // 0xe5
-      5, // 0xe6
-      6, // 0xe7
-      4, // 0xe8
-      5, // 0xe9
-      5, // 0xea
-      6, // 0xeb
-      5, // 0xec
-      6, // 0xed
-      6, // 0xee
-      7, // 0xef
-      4, // 0xf0
-      5, // 0xf1
-      5, // 0xf2
-      6, // 0xf3
-      5, // 0xf4
-      6, // 0xf5
-      6, // 0xf6
-      7, // 0xf7
-      5, // 0xf8
-      6, // 0xf9
-      6, // 0xfa
-      7, // 0xfb
-      6, // 0xfc
-      7, // 0xfd
-      7, // 0xfe
-      8 // 0xff
-  };
-
+    return bitcount(0, value.length - 1);
+  }
 
   public int strlen() {
-    return value.length();
+    return value.length;
   }
 
   public int getbit(int offset) {
     if (offset < 0) {
-      offset += value.length() * 8;
+      offset += value.length * 8;
     }
 
-    if (offset < 0 || offset > value.length() * 8) {
+    if (offset < 0 || offset > value.length * 8) {
       return 0;
     }
 
     int byteIndex = offset / 8;
     offset %= 8;
 
-    if (byteIndex >= value.length()) {
+    if (byteIndex >= value.length) {
       return 0;
     }
 
-    return (value.toBytes()[byteIndex] & (0x80 >> offset)) >> (7 - offset);
+    return (value[byteIndex] & (0x80 >> offset)) >> (7 - offset);
   }
 
   public int setbit(Region<RedisKey, RedisData> region, RedisKey key,
       int bitValue, int byteIndex, byte bitIndex) {
     int returnBit;
-    byte[] bytes = value.toBytes();
+    byte[] bytes = value;
     if (byteIndex < bytes.length) {
       returnBit = (bytes[byteIndex] & (0x80 >> bitIndex)) >> (7 - bitIndex);
     } else {
@@ -596,7 +332,7 @@ public class RedisString extends AbstractRedisData {
       System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
       newBytes[byteIndex] = bitValue == 1 ? (byte) (newBytes[byteIndex] | (0x80 >> bitIndex))
           : (byte) (newBytes[byteIndex] & ~(0x80 >> bitIndex));
-      valueSetBytes(newBytes);
+      value = newBytes;
     }
     // TODO: add delta support
     region.put(key, this);
@@ -613,7 +349,7 @@ public class RedisString extends AbstractRedisData {
   public synchronized void toData(DataOutput out, SerializationContext context) throws IOException {
     super.toData(out, context);
     DataSerializer.writePrimitiveInt(appendSequence, out);
-    DataSerializer.writeByteArray(value.toBytes(), out);
+    DataSerializer.writeByteArray(value, out);
   }
 
   @Override
@@ -621,7 +357,7 @@ public class RedisString extends AbstractRedisData {
       throws IOException, ClassNotFoundException {
     super.fromData(in, context);
     appendSequence = DataSerializer.readPrimitiveInt(in);
-    value = new ByteArrayWrapper(DataSerializer.readByteArray(in));
+    value = DataSerializer.readByteArray(in);
 
   }
 
@@ -636,7 +372,7 @@ public class RedisString extends AbstractRedisData {
     byte[] appendBytes = appendDeltaInfo.getBytes();
 
     if (value == null) {
-      value = new ByteArrayWrapper(appendBytes);
+      value = appendBytes;
       appendSequence = appendDeltaInfo.getSequence();
     } else {
       if (appendDeltaInfo.getSequence() == appendSequence + 1) {
@@ -656,11 +392,10 @@ public class RedisString extends AbstractRedisData {
     return RedisDataType.REDIS_STRING;
   }
 
-  public ByteArrayWrapper getset(Region<RedisKey, RedisData> region, RedisKey key,
-      ByteArrayWrapper newValue) {
+  public byte[] getset(Region<RedisKey, RedisData> region, RedisKey key, byte[] newValue) {
     // No need to copy "value" since we are locked and will be calling set which replaces
     // "value" with a new instance.
-    ByteArrayWrapper result = value;
+    byte[] result = value;
     set(newValue);
     persistNoDelta();
     region.put(key, this);
@@ -684,7 +419,7 @@ public class RedisString extends AbstractRedisData {
       return false;
     }
     RedisString that = (RedisString) o;
-    return Objects.equals(value, that.value);
+    return Arrays.equals(value, that.value);
   }
 
   @Override
@@ -692,7 +427,7 @@ public class RedisString extends AbstractRedisData {
     return Objects.hash(super.hashCode(), value);
   }
 
-  ByteArrayWrapper getValue() {
+  byte[] getValue() {
     return value;
   }
 
@@ -700,7 +435,7 @@ public class RedisString extends AbstractRedisData {
   public String toString() {
     return "RedisString{" +
         super.toString() + ", " +
-        "value=" + value +
+        "value=" + new String(value) +
         '}';
   }
 
@@ -718,15 +453,17 @@ public class RedisString extends AbstractRedisData {
   ////// methods that modify the "value" field ////////////
 
   protected void valueAppend(byte[] bytes) {
-    value.append(bytes);
-  }
-
-  protected void valueSet(ByteArrayWrapper newValue) {
-    value = newValue;
+    int initialLength = value.length;
+    int additionalLength = bytes.length;
+    byte[] combined = new byte[initialLength + additionalLength];
+    System.arraycopy(value, 0, combined, 0, initialLength);
+    System.arraycopy(bytes, 0, combined, initialLength, additionalLength);
+    value = combined;
   }
 
-  protected void valueSetBytes(byte[] bytes) {
-    value.setBytes(bytes);
+  @SuppressWarnings("unused")
+  protected void valueSet(byte[] bytes) {
+    value = bytes;
   }
 
   @Override
@@ -736,6 +473,14 @@ public class RedisString extends AbstractRedisData {
 
   @Override
   public int getSizeInBytes() {
-    return BASE_REDIS_STRING_OVERHEAD + value.length();
+    return BASE_REDIS_STRING_OVERHEAD + value.length;
+  }
+
+  private static byte[] getBitCountTable() {
+    byte[] table = new byte[256];
+    for (int i = 0; i < table.length; ++i) {
+      table[i] = (byte) Integer.bitCount(i);
+    }
+    return table;
   }
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
index f9e6595..ce62e74 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
@@ -27,8 +27,7 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
     implements
     RedisStringCommands {
 
-  public RedisStringCommandsFunctionExecutor(
-      CommandHelper helper) {
+  public RedisStringCommandsFunctionExecutor(CommandHelper helper) {
     super(helper);
   }
 
@@ -41,26 +40,24 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
   }
 
   @Override
-  public long append(RedisKey key, ByteArrayWrapper valueToAppend) {
+  public long append(RedisKey key, byte[] valueToAppend) {
     return stripedExecute(key,
-        () -> getRedisString(key, false)
-            .append(valueToAppend, getRegion(), key));
+        () -> getRedisString(key, false).append(getRegion(), key, valueToAppend));
   }
 
   @Override
-  public ByteArrayWrapper get(RedisKey key) {
+  public byte[] get(RedisKey key) {
     return stripedExecute(key, () -> getRedisString(key, true).get());
   }
 
   @Override
-  public ByteArrayWrapper mget(RedisKey key) {
+  public byte[] mget(RedisKey key) {
     return stripedExecute(key, () -> getRedisStringIgnoringType(key, true).get());
   }
 
   @Override
-  public boolean set(RedisKey key, ByteArrayWrapper value, SetOptions options) {
-    return stripedExecute(key, () -> NULL_REDIS_STRING
-        .set(helper, key, value, options));
+  public boolean set(RedisKey key, byte[] value, SetOptions options) {
+    return stripedExecute(key, () -> NULL_REDIS_STRING.set(helper, key, value, options));
   }
 
   @Override
@@ -74,9 +71,8 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
   }
 
   @Override
-  public ByteArrayWrapper getset(RedisKey key, ByteArrayWrapper value) {
-    return stripedExecute(key,
-        () -> getRedisString(key, true).getset(getRegion(), key, value));
+  public byte[] getset(RedisKey key, byte[] value) {
+    return stripedExecute(key, () -> getRedisString(key, true).getset(getRegion(), key, value));
   }
 
   @Override
@@ -88,13 +84,11 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
   @Override
   public BigDecimal incrbyfloat(RedisKey key, BigDecimal increment) {
     return stripedExecute(key,
-        () -> getRedisString(key, false)
-            .incrbyfloat(getRegion(), key, increment));
+        () -> getRedisString(key, false).incrbyfloat(getRegion(), key, increment));
   }
 
   @Override
-  public int bitop(String operation, RedisKey key,
-      List<RedisKey> sources) {
+  public int bitop(String operation, RedisKey key, List<RedisKey> sources) {
     return NULL_REDIS_STRING.bitop(helper, operation, key, sources);
   }
 
@@ -105,22 +99,19 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
   }
 
   @Override
-  public ByteArrayWrapper getrange(RedisKey key, long start, long end) {
+  public byte[] getrange(RedisKey key, long start, long end) {
     return stripedExecute(key, () -> getRedisString(key, true).getrange(start, end));
   }
 
   @Override
   public int setrange(RedisKey key, int offset, byte[] value) {
     return stripedExecute(key,
-        () -> getRedisString(key, false)
-            .setrange(getRegion(), key, offset, value));
+        () -> getRedisString(key, false).setrange(getRegion(), key, offset, value));
   }
 
   @Override
   public int bitpos(RedisKey key, int bit, int start, Integer end) {
-    return stripedExecute(key,
-        () -> getRedisString(key, true)
-            .bitpos(getRegion(), key, bit, start, end));
+    return stripedExecute(key, () -> getRedisString(key, true).bitpos(bit, start, end));
   }
 
   @Override
@@ -148,8 +139,7 @@ public class RedisStringCommandsFunctionExecutor extends RedisDataCommandsFuncti
     int byteIndex = (int) (offset / 8);
     byte bitIndex = (byte) (offset % 8);
     return stripedExecute(key,
-        () -> getRedisString(key, false)
-            .setbit(getRegion(), key, value, byteIndex, bitIndex));
+        () -> getRedisString(key, false).setbit(getRegion(), key, value, byteIndex, bitIndex));
   }
 
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
index c3bae2e..aab3c59 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
@@ -107,7 +107,7 @@ public class CommandFunction extends SingleResultRedisFunction {
       case INTERNALPTTL:
         return keyCommands.internalPttl(key);
       case APPEND: {
-        ByteArrayWrapper valueToAdd = (ByteArrayWrapper) args[1];
+        byte[] valueToAdd = (byte[]) args[1];
         return stringCommands.append(key, valueToAdd);
       }
       case GET:
@@ -117,12 +117,12 @@ public class CommandFunction extends SingleResultRedisFunction {
       case STRLEN:
         return stringCommands.strlen(key);
       case SET: {
-        ByteArrayWrapper value = (ByteArrayWrapper) args[1];
+        byte[] value = (byte[]) args[1];
         SetOptions options = (SetOptions) args[2];
         return stringCommands.set(key, value, options);
       }
       case GETSET: {
-        ByteArrayWrapper value = (ByteArrayWrapper) args[1];
+        byte[] value = (byte[]) args[1];
         return stringCommands.getset(key, value);
       }
       case GETRANGE: {
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/AppendExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/AppendExecutor.java
index 2cc14eb..ef328cb 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/AppendExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/AppendExecutor.java
@@ -17,7 +17,6 @@ package org.apache.geode.redis.internal.executor.string;
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -28,14 +27,12 @@ public class AppendExecutor extends StringExecutor {
   private static final int VALUE_INDEX = 2;
 
   @Override
-  public RedisResponse executeCommand(Command command,
-      ExecutionHandlerContext context) {
+  public RedisResponse executeCommand(Command command, ExecutionHandlerContext context) {
     List<byte[]> commandElems = command.getProcessedCommand();
     RedisKey key = command.getKey();
     byte[] bytesToAppend = commandElems.get(VALUE_INDEX);
-    ByteArrayWrapper valueToAppend = new ByteArrayWrapper(bytesToAppend);
 
-    long returnValue = getRedisStringCommands(context).append(key, valueToAppend);
+    long returnValue = getRedisStringCommands(context).append(key, bytesToAppend);
 
     return RedisResponse.integer(returnValue);
   }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetExecutor.java
index 5b60d90..a2c8bba 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetExecutor.java
@@ -14,7 +14,6 @@
  */
 package org.apache.geode.redis.internal.executor.string;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -23,12 +22,11 @@ import org.apache.geode.redis.internal.netty.ExecutionHandlerContext;
 public class GetExecutor extends StringExecutor {
 
   @Override
-  public RedisResponse executeCommand(Command command,
-      ExecutionHandlerContext context) {
+  public RedisResponse executeCommand(Command command, ExecutionHandlerContext context) {
 
     RedisKey key = command.getKey();
     RedisStringCommands redisStringCommands = getRedisStringCommands(context);
-    ByteArrayWrapper result = redisStringCommands.get(key);
+    byte[] result = redisStringCommands.get(key);
 
     return respondBulkStrings(result);
   }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java
index 605904b..263fe68 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java
@@ -18,7 +18,6 @@ import static org.apache.geode.redis.internal.RedisConstants.ERROR_NOT_INTEGER;
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Coder;
@@ -49,11 +48,11 @@ public class GetRangeExecutor extends StringExecutor {
     RedisStringCommands stringCommands = getRedisStringCommands(context);
     RedisKey key = command.getKey();
 
-    ByteArrayWrapper returnRange = stringCommands.getrange(key, start, end);
+    byte[] returnRange = stringCommands.getrange(key, start, end);
 
     if (returnRange == null) {
       return RedisResponse.nil();
-    } else if (returnRange.length() == 0) {
+    } else if (returnRange.length == 0) {
       return RedisResponse.emptyString();
     } else {
       return respondBulkStrings(returnRange);
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetSetExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetSetExecutor.java
index c26d33d..ec3ffb3 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetSetExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetSetExecutor.java
@@ -17,7 +17,6 @@ package org.apache.geode.redis.internal.executor.string;
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -33,10 +32,9 @@ public class GetSetExecutor extends StringExecutor {
 
     RedisKey key = command.getKey();
     byte[] newCharValue = commandElems.get(VALUE_INDEX);
-    ByteArrayWrapper newValueWrapper = new ByteArrayWrapper(newCharValue);
 
     RedisStringCommands stringCommands = getRedisStringCommands(context);
-    ByteArrayWrapper oldValueWrapper = stringCommands.getset(key, newValueWrapper);
+    byte[] oldValueWrapper = stringCommands.getset(key, newCharValue);
 
     return respondBulkStrings(oldValueWrapper);
   }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MGetExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MGetExecutor.java
index 2447241..d65a0f76 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MGetExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MGetExecutor.java
@@ -18,7 +18,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -31,7 +30,7 @@ public class MGetExecutor extends StringExecutor {
     List<byte[]> commandElems = command.getProcessedCommand();
     RedisStringCommands stringCommands = getRedisStringCommands(context);
 
-    Collection<ByteArrayWrapper> values = new ArrayList<>();
+    Collection<byte[]> values = new ArrayList<>();
     for (int i = 1; i < commandElems.size(); i++) {
       byte[] keyArray = commandElems.get(i);
       RedisKey key = new RedisKey(keyArray);
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetExecutor.java
index 98ce50a..26298a5 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetExecutor.java
@@ -16,7 +16,6 @@ package org.apache.geode.redis.internal.executor.string;
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -37,8 +36,7 @@ public class MSetExecutor extends StringExecutor {
       byte[] keyArray = commandElems.get(i);
       RedisKey key = new RedisKey(keyArray);
       byte[] valueArray = commandElems.get(i + 1);
-      ByteArrayWrapper value = new ByteArrayWrapper(valueArray);
-      stringCommands.set(key, value, null);
+      stringCommands.set(key, valueArray, null);
     }
 
     return RedisResponse.string(SUCCESS);
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetNXExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetNXExecutor.java
index d3ac56a..c289662 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetNXExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/MSetNXExecutor.java
@@ -17,7 +17,6 @@ package org.apache.geode.redis.internal.executor.string;
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.executor.key.RedisKeyCommands;
@@ -51,8 +50,7 @@ public class MSetNXExecutor extends StringExecutor {
       byte[] keyArray = commandElems.get(i);
       RedisKey key = new RedisKey(keyArray);
       byte[] valueArray = commandElems.get(i + 1);
-      ByteArrayWrapper value = new ByteArrayWrapper(valueArray);
-      stringCommands.set(key, value, null);
+      stringCommands.set(key, valueArray, null);
     }
 
     return RedisResponse.integer(SET);
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
index f4f6f5c..8d4b94f 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
@@ -17,27 +17,26 @@ package org.apache.geode.redis.internal.executor.string;
 import java.math.BigDecimal;
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 
 public interface RedisStringCommands {
-  long append(RedisKey key, ByteArrayWrapper valueToAppend);
+  long append(RedisKey key, byte[] valueToAppend);
 
-  ByteArrayWrapper get(RedisKey key);
+  byte[] get(RedisKey key);
 
-  boolean set(RedisKey key, ByteArrayWrapper value, SetOptions options);
+  boolean set(RedisKey key, byte[] value, SetOptions options);
 
   long incr(RedisKey key);
 
   long decr(RedisKey key);
 
-  ByteArrayWrapper getset(RedisKey key, ByteArrayWrapper value);
+  byte[] getset(RedisKey key, byte[] value);
 
   long incrby(RedisKey key, long increment);
 
   long decrby(RedisKey key, long decrement);
 
-  ByteArrayWrapper getrange(RedisKey key, long start, long end);
+  byte[] getrange(RedisKey key, long start, long end);
 
   long bitcount(RedisKey key, int start, int end);
 
@@ -57,5 +56,5 @@ public interface RedisStringCommands {
 
   int setrange(RedisKey key, int offset, byte[] value);
 
-  ByteArrayWrapper mget(RedisKey key);
+  byte[] mget(RedisKey key);
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionInvoker.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionInvoker.java
index 79b6cd2..9d4b2ec 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionInvoker.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionInvoker.java
@@ -37,7 +37,6 @@ import java.math.BigDecimal;
 import java.util.List;
 
 import org.apache.geode.cache.Region;
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisData;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisCommandsFunctionInvoker;
@@ -55,17 +54,17 @@ public class RedisStringCommandsFunctionInvoker extends RedisCommandsFunctionInv
   }
 
   @Override
-  public long append(RedisKey key, ByteArrayWrapper valueToAppend) {
+  public long append(RedisKey key, byte[] valueToAppend) {
     return invokeCommandFunction(key, APPEND, valueToAppend);
   }
 
   @Override
-  public ByteArrayWrapper get(RedisKey key) {
+  public byte[] get(RedisKey key) {
     return invokeCommandFunction(key, GET);
   }
 
   @Override
-  public boolean set(RedisKey key, ByteArrayWrapper value, SetOptions options) {
+  public boolean set(RedisKey key, byte[] value, SetOptions options) {
     return invokeCommandFunction(key, SET, value, options);
   }
 
@@ -80,7 +79,7 @@ public class RedisStringCommandsFunctionInvoker extends RedisCommandsFunctionInv
   }
 
   @Override
-  public ByteArrayWrapper getset(RedisKey key, ByteArrayWrapper value) {
+  public byte[] getset(RedisKey key, byte[] value) {
     return invokeCommandFunction(key, GETSET, value);
   }
 
@@ -95,7 +94,7 @@ public class RedisStringCommandsFunctionInvoker extends RedisCommandsFunctionInv
   }
 
   @Override
-  public ByteArrayWrapper getrange(RedisKey key, long start, long end) {
+  public byte[] getrange(RedisKey key, long start, long end) {
     return invokeCommandFunction(key, GETRANGE, start, end);
   }
 
@@ -145,7 +144,7 @@ public class RedisStringCommandsFunctionInvoker extends RedisCommandsFunctionInv
   }
 
   @Override
-  public ByteArrayWrapper mget(RedisKey key) {
+  public byte[] mget(RedisKey key) {
     return invokeCommandFunction(key, MGET);
   }
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetEXExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetEXExecutor.java
index c4d2c53..a466ac1 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetEXExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetEXExecutor.java
@@ -19,7 +19,6 @@ import static org.apache.geode.redis.internal.executor.string.SetOptions.Exists.
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Coder;
@@ -64,7 +63,7 @@ public class SetEXExecutor extends StringExecutor {
     }
     SetOptions setOptions = new SetOptions(NONE, expiration, false);
 
-    stringCommands.set(key, new ByteArrayWrapper(value), setOptions);
+    stringCommands.set(key, value, setOptions);
 
     return RedisResponse.string(SUCCESS);
   }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetExecutor.java
index a2b71fa..8aa9474 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetExecutor.java
@@ -24,7 +24,6 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Coder;
@@ -33,16 +32,15 @@ import org.apache.geode.redis.internal.netty.ExecutionHandlerContext;
 
 public class SetExecutor extends StringExecutor {
 
+  private static final int VALUE_INDEX = 2;
   private static final String SUCCESS = "OK";
 
   @Override
-  public RedisResponse executeCommand(Command command,
-      ExecutionHandlerContext context) {
+  public RedisResponse executeCommand(Command command, ExecutionHandlerContext context) {
 
     RedisKey keyToSet = command.getKey();
     List<byte[]> commandElementsBytes = command.getProcessedCommand();
     List<byte[]> optionalParameterBytes = getOptionalParameters(commandElementsBytes);
-    ByteArrayWrapper valueToSet = getValueToSet(commandElementsBytes);
     RedisStringCommands redisStringCommands = getRedisStringCommands(context);
     SetOptions setOptions;
 
@@ -52,15 +50,15 @@ public class SetExecutor extends StringExecutor {
       return RedisResponse.error(ex.getMessage());
     }
 
-    return doSet(keyToSet, valueToSet, redisStringCommands, setOptions);
+    return doSet(keyToSet, commandElementsBytes.get(VALUE_INDEX), redisStringCommands, setOptions);
   }
 
   private List<byte[]> getOptionalParameters(List<byte[]> commandElementsBytes) {
     return commandElementsBytes.subList(3, commandElementsBytes.size());
   }
 
-  private RedisResponse doSet(RedisKey key, ByteArrayWrapper value,
-      RedisStringCommands redisStringCommands, SetOptions setOptions) {
+  private RedisResponse doSet(RedisKey key, byte[] value, RedisStringCommands redisStringCommands,
+      SetOptions setOptions) {
 
     boolean setCompletedSuccessfully = redisStringCommands.set(key, value, setOptions);
 
@@ -71,11 +69,6 @@ public class SetExecutor extends StringExecutor {
     }
   }
 
-  private ByteArrayWrapper getValueToSet(List<byte[]> commandElems) {
-    byte[] value = commandElems.get(2);
-    return new ByteArrayWrapper(value);
-  }
-
   private SetOptions parseOptionalParameters(List<byte[]> optionalParameterBytes)
       throws IllegalArgumentException {
 
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetNXExecutor.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetNXExecutor.java
index 8aa6fae..68abf53 100755
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetNXExecutor.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetNXExecutor.java
@@ -18,7 +18,6 @@ import static org.apache.geode.redis.internal.executor.string.SetOptions.Exists.
 
 import java.util.List;
 
-import org.apache.geode.redis.internal.data.ByteArrayWrapper;
 import org.apache.geode.redis.internal.data.RedisKey;
 import org.apache.geode.redis.internal.executor.RedisResponse;
 import org.apache.geode.redis.internal.netty.Command;
@@ -32,12 +31,11 @@ public class SetNXExecutor extends StringExecutor {
   public RedisResponse executeCommand(Command command, ExecutionHandlerContext context) {
     List<byte[]> commandElems = command.getProcessedCommand();
     RedisKey key = command.getKey();
-    ByteArrayWrapper value = new ByteArrayWrapper(commandElems.get(VALUE_INDEX));
 
     RedisStringCommands stringCommands = getRedisStringCommands(context);
     SetOptions setOptions = new SetOptions(NX, 0L, false);
 
-    boolean result = stringCommands.set(key, value, setOptions);
+    boolean result = stringCommands.set(key, commandElems.get(VALUE_INDEX), setOptions);
 
     return RedisResponse.integer(result);
   }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
index b9667ff..b4b4f42 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
@@ -76,8 +76,7 @@ public class SetOptions implements DataSerializableFixedID {
   }
 
   @Override
-  public void fromData(DataInput in, DeserializationContext context)
-      throws IOException, ClassNotFoundException {
+  public void fromData(DataInput in, DeserializationContext context) throws IOException {
     exists = DataSerializer.readEnum(SetOptions.Exists.class, in);
     expirationMillis = in.readLong();
     keepTTL = in.readBoolean();
@@ -99,6 +98,6 @@ public class SetOptions implements DataSerializableFixedID {
     /**
      * Only set if key already exists
      */
-    XX;
+    XX
   }
 }
diff --git a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/netty/Coder.java b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/netty/Coder.java
index 14a31d5..326aab4 100644
--- a/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/netty/Coder.java
+++ b/geode-apis-compatible-with-redis/src/main/java/org/apache/geode/redis/internal/netty/Coder.java
@@ -171,20 +171,12 @@ public class Coder {
     return buffer;
   }
 
-  private static void writeCollectionOrString(ByteBuf buffer, Object next)
-      throws CoderException {
-    ByteBuf tmp = null;
-    try {
-      if (next instanceof Collection) {
-        Collection<?> nextItems = (Collection<?>) next;
-        getArrayResponse(buffer, nextItems);
-      } else {
-        getBulkStringResponse(buffer, next);
-      }
-    } finally {
-      if (tmp != null) {
-        tmp.release();
-      }
+  private static void writeCollectionOrString(ByteBuf buffer, Object next) throws CoderException {
+    if (next instanceof Collection) {
+      Collection<?> nextItems = (Collection<?>) next;
+      getArrayResponse(buffer, nextItems);
+    } else {
+      getBulkStringResponse(buffer, next);
     }
   }
 
diff --git a/geode-apis-compatible-with-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java b/geode-apis-compatible-with-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
index 50481bb..79d9133 100644
--- a/geode-apis-compatible-with-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
+++ b/geode-apis-compatible-with-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
@@ -17,6 +17,7 @@
 package org.apache.geode.redis.internal.data;
 
 import static org.apache.geode.redis.internal.data.RedisString.BASE_REDIS_STRING_OVERHEAD;
+import static org.apache.geode.util.internal.UncheckedUtils.uncheckedCast;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.mock;
@@ -26,6 +27,7 @@ import java.io.IOException;
 import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
 
+import org.apache.commons.lang3.StringUtils;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -43,9 +45,6 @@ public class RedisStringTest {
 
   @BeforeClass
   public static void beforeClass() {
-    InternalDataSerializer
-        .getDSFIDSerializer()
-        .registerDSFID(DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER, ByteArrayWrapper.class);
     InternalDataSerializer.getDSFIDSerializer().registerDSFID(
         DataSerializableFixedID.REDIS_STRING_ID,
         RedisString.class);
@@ -53,75 +52,78 @@ public class RedisStringTest {
 
   @Test
   public void constructorSetsValue() {
-    ByteArrayWrapper byteArrayWrapper = new ByteArrayWrapper(new byte[] {0, 1, 2});
-    RedisString string = new RedisString(byteArrayWrapper);
-    ByteArrayWrapper returnedByteArrayWrapper = string.get();
-    assertThat(returnedByteArrayWrapper).isNotNull();
-    assertThat(returnedByteArrayWrapper.value).isEqualTo(byteArrayWrapper.value);
+    byte[] bytes = {0, 1, 2};
+    RedisString string = new RedisString(bytes);
+    byte[] returnedBytes = string.get();
+    assertThat(returnedBytes).isNotNull();
+    assertThat(returnedBytes).isEqualTo(bytes);
   }
 
   @Test
   public void setSetsValue() {
     RedisString string = new RedisString();
-    string.set(new ByteArrayWrapper(new byte[] {0, 1, 2}));
-    ByteArrayWrapper returnedByteArrayWrapper = string.get();
-    assertThat(returnedByteArrayWrapper).isNotNull();
-    assertThat(returnedByteArrayWrapper.value)
-        .isEqualTo(new ByteArrayWrapper(new byte[] {0, 1, 2}).value);
+    byte[] bytes = {0, 1, 2};
+    string.set(bytes);
+    byte[] returnedBytes = string.get();
+    assertThat(returnedBytes).isNotNull();
+    assertThat(returnedBytes).isEqualTo(bytes);
   }
 
   @Test
   public void getReturnsSetValue() {
-    RedisString string = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    ByteArrayWrapper returnedByteArrayWrapper = string.get();
-    assertThat(returnedByteArrayWrapper).isNotNull();
-    assertThat(returnedByteArrayWrapper.value)
-        .isEqualTo(new ByteArrayWrapper(new byte[] {0, 1}).value);
+    byte[] bytes = {0, 1};
+    RedisString string = new RedisString(bytes);
+    byte[] returnedBytes = string.get();
+    assertThat(returnedBytes).isNotNull();
+    assertThat(returnedBytes).isEqualTo(bytes);
   }
 
   @Test
   public void appendResizesByteArray() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisString redisString = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    ByteArrayWrapper part2 = new ByteArrayWrapper(new byte[] {2, 3, 4, 5});
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    RedisString redisString = new RedisString(new byte[] {0, 1});
     int redisStringSize = redisString.strlen();
-    int part2Size = part2.length();
-    int appendedStringSize = redisString.append(part2, region, null);
-    assertThat(appendedStringSize).isEqualTo(redisStringSize + part2Size);
+    byte[] bytesToAppend = {2, 3, 4, 5};
+    int appendedSize = bytesToAppend.length;
+    int appendedStringSize = redisString.append(region, null, bytesToAppend);
+    assertThat(appendedStringSize).isEqualTo(redisStringSize + appendedSize);
   }
 
   @Test
   public void appendStoresStableDelta() throws IOException {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    ByteArrayWrapper part2 = new ByteArrayWrapper(new byte[] {2, 3});
-    o1.append(part2, region, null);
-    assertThat(o1.hasDelta()).isTrue();
-    assertThat(o1.get()).isEqualTo(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] baseBytes = {0, 1};
+    byte[] bytesToAppend = {2, 3};
+    byte[] baseAndAppendedBytes = {0, 1, 2, 3};
+
+    RedisString stringOne = new RedisString(baseBytes);
+    stringOne.append(region, null, bytesToAppend);
+    assertThat(stringOne.hasDelta()).isTrue();
+    assertThat(stringOne.get()).isEqualTo(baseAndAppendedBytes);
     HeapDataOutputStream out = new HeapDataOutputStream(100);
-    o1.toDelta(out);
-    assertThat(o1.hasDelta()).isFalse();
+    stringOne.toDelta(out);
+    assertThat(stringOne.hasDelta()).isFalse();
     ByteArrayDataInput in = new ByteArrayDataInput(out.toByteArray());
-    RedisString o2 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    assertThat(o2).isNotEqualTo(o1);
-    o2.fromDelta(in);
-    assertThat(o2.get()).isEqualTo(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    assertThat(o2).isEqualTo(o1);
+    RedisString stringTwo = new RedisString(baseBytes);
+    assertThat(stringTwo).isNotEqualTo(stringOne);
+    stringTwo.fromDelta(in);
+    assertThat(stringTwo.get()).isEqualTo(baseAndAppendedBytes);
+    assertThat(stringTwo).isEqualTo(stringOne);
   }
 
   @Test
   public void confirmSerializationIsStable() throws IOException, ClassNotFoundException {
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o1.setExpirationTimestampNoDelta(1000);
+    RedisString stringOne = new RedisString(new byte[] {0, 1, 2, 3});
+    int expirationTimestamp = 1000;
+    stringOne.setExpirationTimestampNoDelta(expirationTimestamp);
     HeapDataOutputStream outputStream = new HeapDataOutputStream(100);
-    DataSerializer.writeObject(o1, outputStream);
+    DataSerializer.writeObject(stringOne, outputStream);
     ByteArrayDataInput dataInput = new ByteArrayDataInput(outputStream.toByteArray());
-    RedisString o2 = DataSerializer.readObject(dataInput);
-    assertThat(o2).isEqualTo(o1);
+    RedisString stringTwo = DataSerializer.readObject(dataInput);
+    assertThat(stringTwo).isEqualTo(stringOne);
+    assertThat(stringTwo.getExpirationTimestamp())
+        .isEqualTo(stringOne.getExpirationTimestamp())
+        .isEqualTo(expirationTimestamp);
   }
 
   @Test
@@ -134,225 +136,191 @@ public class RedisStringTest {
 
   @Test
   public void incrThrowsArithmeticErrorWhenNotALong() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0', ' ', '1'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.incr(region, byteArrayWrapper))
-        .isInstanceOf(NumberFormatException.class);
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10 1".getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.incr(region, null)).isInstanceOf(NumberFormatException.class);
   }
 
   @Test
   public void incrErrorsWhenValueOverflows() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(
-        // max value for signed long
-        new byte[] {'9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7', '5',
-            '8', '0', '7'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.incr(region, byteArrayWrapper))
-        .isInstanceOf(ArithmeticException.class);
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = String.valueOf(Long.MAX_VALUE).getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.incr(region, null)).isInstanceOf(ArithmeticException.class);
   }
 
   @Test
   public void incrIncrementsValueAtGivenKey() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    string.incr(region, byteArrayWrapper);
-    assertThat(string.get().toString()).isEqualTo("11");
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10".getBytes();
+    RedisString string = new RedisString(bytes);
+    string.incr(region, null);
+    assertThat(string.get()).isEqualTo("11".getBytes());
   }
 
   @Test
   public void incrbyThrowsNumberFormatExceptionWhenNotALong() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0', ' ', '1'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.incrby(region, byteArrayWrapper, 2L))
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10 1".getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.incrby(region, null, 2L))
         .isInstanceOf(NumberFormatException.class);
   }
 
   @Test
   public void incrbyErrorsWhenValueOverflows() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(
-        // max value for signed long
-        new byte[] {'9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7', '5',
-            '8', '0', '7'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.incrby(region, byteArrayWrapper, 2L))
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = String.valueOf(Long.MAX_VALUE).getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.incrby(region, null, 2L))
         .isInstanceOf(ArithmeticException.class);
   }
 
   @Test
   public void incrbyIncrementsValueByGivenLong() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    string.incrby(region, byteArrayWrapper, 2L);
-    assertThat(string.get().toString()).isEqualTo("12");
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10".getBytes();
+    RedisString string = new RedisString(bytes);
+    string.incrby(region, null, 2L);
+    assertThat(string.get()).isEqualTo("12".getBytes());
   }
 
   @Test
   public void incrbyfloatThrowsArithmeticErrorWhenNotADouble() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0', ' ', '1'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.incrbyfloat(region, byteArrayWrapper, new BigDecimal("1.1")))
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10 1".getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.incrbyfloat(region, null, new BigDecimal("1.1")))
         .isInstanceOf(NumberFormatException.class);
   }
 
   @Test
   public void incrbyfloatIncrementsValueByGivenFloat() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    string.incrbyfloat(region, byteArrayWrapper, new BigDecimal("2.20"));
-    assertThat(string.get().toString()).isEqualTo("12.20");
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10".getBytes();
+    RedisString string = new RedisString(bytes);
+    string.incrbyfloat(region, null, new BigDecimal("2.20"));
+    assertThat(string.get()).isEqualTo("12.20".getBytes());
   }
 
   @Test
   public void decrThrowsNumberFormatExceptionWhenNotALong() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {0});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.decr(region, byteArrayWrapper))
-        .isInstanceOf(NumberFormatException.class);
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = {0};
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.decr(region, null)).isInstanceOf(NumberFormatException.class);
   }
 
   @Test
   public void decrThrowsArithmeticExceptionWhenDecrementingMin() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(
-        new byte[] {'-', '9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7',
-            '5',
-            '8', '0', '8'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.decr(region, byteArrayWrapper))
-        .isInstanceOf(ArithmeticException.class);
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = String.valueOf(Long.MIN_VALUE).getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.decr(region, null)).isInstanceOf(ArithmeticException.class);
   }
 
   @Test
   public void decrDecrementsValue() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    string.decr(region, byteArrayWrapper);
-    assertThat(string.get().toString()).isEqualTo("9");
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10".getBytes();
+    RedisString string = new RedisString(bytes);
+    string.decr(region, null);
+    assertThat(string.get()).isEqualTo("9".getBytes());
   }
 
   @Test
   public void decrbyThrowsNumberFormatExceptionWhenNotALong() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {1});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.decrby(region, byteArrayWrapper, 2))
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = {1};
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.decrby(region, null, 2))
         .isInstanceOf(NumberFormatException.class);
   }
 
   @Test
   public void decrbyThrowsArithmeticExceptionWhenDecrementingMin() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(
-        new byte[] {'-', '9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7',
-            '5',
-            '8', '0', '7'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    assertThatThrownBy(() -> string.decrby(region, byteArrayWrapper, 2))
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = String.valueOf(Long.MIN_VALUE).getBytes();
+    RedisString string = new RedisString(bytes);
+    assertThatThrownBy(() -> string.decrby(region, null, 2))
         .isInstanceOf(ArithmeticException.class);
   }
 
   @Test
   public void decrbyDecrementsValue() {
-    // allows unchecked cast of mock to Region<RedisKey, RedisData>
-    @SuppressWarnings("unchecked")
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisKey byteArrayWrapper = new RedisKey(new byte[] {'1', '0'});
-    RedisString string = new RedisString(byteArrayWrapper);
-    string.decrby(region, byteArrayWrapper, 2);
-    assertThat(string.get().toString()).isEqualTo("8");
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = "10".getBytes();
+    RedisString string = new RedisString(bytes);
+    string.decrby(region, null, 2);
+    assertThat(string.get()).isEqualTo("8".getBytes());
   }
 
   @Test
   public void strlenReturnsStringLength() {
-    RedisString string = new RedisString(new ByteArrayWrapper(new byte[] {1, 2, 3, 4}));
-    assertThat(string.strlen()).isEqualTo(4);
+    byte[] bytes = {1, 2, 3, 4};
+    RedisString string = new RedisString(bytes);
+    assertThat(string.strlen()).isEqualTo(bytes.length);
   }
 
   @Test
   public void strlenReturnsLengthOfEmptyString() {
-    RedisString string = new RedisString(new ByteArrayWrapper(new byte[] {}));
+    RedisString string = new RedisString(new byte[] {});
     assertThat(string.strlen()).isEqualTo(0);
   }
 
   @Test
   public void equals_returnsFalse_givenDifferentExpirationTimes() {
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o1.setExpirationTimestampNoDelta(1000);
-    RedisString o2 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o2.setExpirationTimestampNoDelta(999);
-    assertThat(o1).isNotEqualTo(o2);
+    byte[] bytes = {0, 1, 2, 3};
+    RedisString stringOne = new RedisString(bytes);
+    stringOne.setExpirationTimestampNoDelta(1000);
+    RedisString stringTwo = new RedisString(bytes);
+    stringTwo.setExpirationTimestampNoDelta(999);
+    assertThat(stringOne).isNotEqualTo(stringTwo);
   }
 
   @Test
   public void equals_returnsFalse_givenDifferentValueBytes() {
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o1.setExpirationTimestampNoDelta(1000);
-    RedisString o2 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 2}));
-    o2.setExpirationTimestampNoDelta(1000);
-    assertThat(o1).isNotEqualTo(o2);
+    int expirationTimestamp = 1000;
+    RedisString stringOne = new RedisString(new byte[] {0, 1, 2, 3});
+    stringOne.setExpirationTimestampNoDelta(expirationTimestamp);
+    RedisString stringTwo = new RedisString(new byte[] {0, 1, 2, 2});
+    stringTwo.setExpirationTimestampNoDelta(expirationTimestamp);
+    assertThat(stringOne).isNotEqualTo(stringTwo);
   }
 
   @Test
   public void equals_returnsTrue_givenEqualValueBytesAndExpiration() {
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o1.setExpirationTimestampNoDelta(1000);
-    RedisString o2 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
-    o2.setExpirationTimestampNoDelta(1000);
-    assertThat(o1).isEqualTo(o2);
+    byte[] bytes = {0, 1, 2, 3};
+    int expirationTimestamp = 1000;
+    RedisString stringOne = new RedisString(bytes);
+    stringOne.setExpirationTimestampNoDelta(expirationTimestamp);
+    RedisString stringTwo = new RedisString(bytes);
+    stringTwo.setExpirationTimestampNoDelta(expirationTimestamp);
+    assertThat(stringOne).isEqualTo(stringTwo);
   }
 
-
-  @SuppressWarnings("unchecked")
   @Test
   public void setExpirationTimestamp_stores_delta_that_is_stable() throws IOException {
-    Region<RedisKey, RedisData> region = mock(Region.class);
-    RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    o1.setExpirationTimestamp(region, null, 999);
-    assertThat(o1.hasDelta()).isTrue();
+    Region<RedisKey, RedisData> region = uncheckedCast(mock(Region.class));
+    byte[] bytes = {0, 1};
+    RedisString stringOne = new RedisString(bytes);
+    stringOne.setExpirationTimestamp(region, null, 999);
+    assertThat(stringOne.hasDelta()).isTrue();
     HeapDataOutputStream out = new HeapDataOutputStream(100);
-    o1.toDelta(out);
-    assertThat(o1.hasDelta()).isFalse();
+    stringOne.toDelta(out);
+    assertThat(stringOne.hasDelta()).isFalse();
     ByteArrayDataInput in = new ByteArrayDataInput(out.toByteArray());
-    RedisString o2 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1}));
-    assertThat(o2).isNotEqualTo(o1);
-    o2.fromDelta(in);
-    assertThat(o2).isEqualTo(o1);
+    RedisString stringTwo = new RedisString(bytes);
+    assertThat(stringTwo).isNotEqualTo(stringOne);
+    stringTwo.fromDelta(in);
+    assertThat(stringTwo).isEqualTo(stringOne);
+  }
+
+  @Test
+  public void bitposReturnsNegativeOneWhenBitIsNotZeroOrOne() {
+    RedisString string = new RedisString(new byte[] {0, 1});
+    assertThat(string.bitpos(2, 0, 1)).isEqualTo(-1);
   }
 
   /************* Size in Bytes Tests *************/
@@ -360,7 +328,7 @@ public class RedisStringTest {
   @Test
   public void should_calculateSize_equalToROSSize_ofLargeStrings() {
     String javaString = makeStringOfSpecifiedSize(10_000);
-    RedisString string = new RedisString(new ByteArrayWrapper(javaString.getBytes()));
+    RedisString string = new RedisString(javaString.getBytes());
 
     int actual = string.getSizeInBytes();
     int expected = reflectionObjectSizer.sizeof(string);
@@ -373,7 +341,7 @@ public class RedisStringTest {
     String javaString;
     for (int i = 0; i < 512; i += 8) {
       javaString = makeStringOfSpecifiedSize(i);
-      RedisString string = new RedisString(new ByteArrayWrapper(javaString.getBytes()));
+      RedisString string = new RedisString(javaString.getBytes());
 
       int expected = reflectionObjectSizer.sizeof(string);
       int actual = string.getSizeInBytes();
@@ -386,37 +354,39 @@ public class RedisStringTest {
   @Test
   public void changingStringValue_toShorterString_shouldDecreaseSizeInBytes() {
     String baseString = "baseString";
-    RedisString string = new RedisString(new ByteArrayWrapper((baseString + "asdf").getBytes()));
+    String stringToRemove = "asdf";
+    RedisString string = new RedisString((baseString + stringToRemove).getBytes());
 
     int initialSize = string.getSizeInBytes();
 
-    string.set(new ByteArrayWrapper(baseString.getBytes()));
+    string.set(baseString.getBytes());
 
     int finalSize = string.getSizeInBytes();
 
-    assertThat(finalSize).isEqualTo(initialSize - 4);
+    assertThat(finalSize).isEqualTo(initialSize - stringToRemove.length());
   }
 
   @Test
   public void changingStringValue_toLongerString_shouldIncreaseSizeInBytes() {
     String baseString = "baseString";
-    RedisString string = new RedisString(new ByteArrayWrapper(baseString.getBytes()));
+    RedisString string = new RedisString(baseString.getBytes());
 
     int initialSize = string.getSizeInBytes();
 
-    string.set(new ByteArrayWrapper((baseString + "asdf").getBytes()));
+    String addedString = "asdf";
+    string.set((baseString + addedString).getBytes());
 
     int finalSize = string.getSizeInBytes();
 
-    assertThat(finalSize).isEqualTo(initialSize + 4);
+    assertThat(finalSize).isEqualTo(initialSize + addedString.length());
   }
 
   @Test
   public void changingStringValue_toEmptyString_shouldDecreaseSizeInBytes_toBaseSize() {
     String baseString = "baseString";
-    RedisString string = new RedisString(new ByteArrayWrapper((baseString + "asdf").getBytes()));
+    RedisString string = new RedisString((baseString + "asdf").getBytes());
 
-    string.set(new ByteArrayWrapper("".getBytes()));
+    string.set("".getBytes());
 
     int finalSize = string.getSizeInBytes();
 
@@ -430,7 +400,7 @@ public class RedisStringTest {
   // carefully consider that increase before changing the constant.
   @Test
   public void overheadConstants_shouldMatchCalculatedValue() {
-    RedisString redisString = new RedisString(new ByteArrayWrapper("".getBytes()));
+    RedisString redisString = new RedisString("".getBytes());
     int calculatedSize = reflectionObjectSizer.sizeof(redisString);
 
     assertThat(BASE_REDIS_STRING_OVERHEAD).isEqualTo(calculatedSize);
@@ -439,10 +409,6 @@ public class RedisStringTest {
   /******* helper methods *******/
 
   private String makeStringOfSpecifiedSize(final int stringSize) {
-    StringBuffer sb = new StringBuffer(stringSize);
-    for (int i = 0; i < stringSize; i++) {
-      sb.append("a");
-    }
-    return sb.toString();
+    return StringUtils.repeat("a", stringSize);
   }
 }