diff --git a/core/java/src/net/i2p/crypto/CryptixAESEngine.java b/core/java/src/net/i2p/crypto/CryptixAESEngine.java
index 4febf45e47a6a320e0b7fc5b58ef248cf5ef00e3..6d8e0da07579f0c4012feece0173d3dfa173766f 100644
--- a/core/java/src/net/i2p/crypto/CryptixAESEngine.java
+++ b/core/java/src/net/i2p/crypto/CryptixAESEngine.java
@@ -21,8 +21,8 @@ import net.i2p.I2PAppContext;
 import net.i2p.data.ByteArray;
 import net.i2p.data.DataHelper;
 import net.i2p.data.SessionKey;
-import net.i2p.util.ByteCache;
 import net.i2p.util.Log;
+import net.i2p.util.SimpleByteCache;
 
 /** 
  * Wrapper for AES cypher operation using Cryptix's Rijndael implementation.  Implements
@@ -38,8 +38,6 @@ public class CryptixAESEngine extends AESEngine {
     // keys are now cached in the SessionKey objects
     //private CryptixAESKeyCache _cache;
     
-    private static final ByteCache _prevCache = ByteCache.getInstance(16, 16);
-    
 /**** see comments for main() below
     private static final boolean USE_SYSTEM_AES;
     static {
@@ -166,10 +164,8 @@ public class CryptixAESEngine extends AESEngine {
         int numblock = length / 16;
         if (length % 16 != 0) numblock++;
 
-        ByteArray prevA = _prevCache.acquire();
-        byte prev[] = prevA.getData();
-        ByteArray curA = _prevCache.acquire();
-        byte cur[] = curA.getData();
+        byte prev[] = SimpleByteCache.acquire(16);
+        byte cur[] = SimpleByteCache.acquire(16);
         System.arraycopy(iv, ivOffset, prev, 0, 16);
         
         for (int x = 0; x < numblock; x++) {
@@ -190,8 +186,8 @@ public class CryptixAESEngine extends AESEngine {
         }
          */
         
-        _prevCache.release(prevA);
-        _prevCache.release(curA);
+        SimpleByteCache.release(prev);
+        SimpleByteCache.release(cur);
     }
     
     /** encrypt exactly 16 bytes using the session key
diff --git a/core/java/src/net/i2p/data/SDSCache.java b/core/java/src/net/i2p/data/SDSCache.java
index 474e96479142c57289e6863fe3acc22634c6d5d6..e8f7d302d61498b0c1cab5d9221d88ebd2a95903 100644
--- a/core/java/src/net/i2p/data/SDSCache.java
+++ b/core/java/src/net/i2p/data/SDSCache.java
@@ -98,6 +98,11 @@ public class SDSCache<V extends SimpleDataStructure> {
     }
 
     /**
+     *  WARNING - If the SDS is found in the cache, the passed-in
+     *  byte array will be returned to the SimpleByteCache for reuse.
+     *  Do NOT save a reference to the passed-in data, or use or modify it,
+     *  after this call.
+     *
      *  @param data non-null, the byte array for the SimpleDataStructure
      *  @return the cached value if available, otherwise
      *          makes a new object and returns it
diff --git a/core/java/src/net/i2p/util/ByteCache.java b/core/java/src/net/i2p/util/ByteCache.java
index d4ea7132d5bf00e8664b142b3e7224ad25fd22ac..7253a472e89a8fa3630863b093abffdc4854b5aa 100644
--- a/core/java/src/net/i2p/util/ByteCache.java
+++ b/core/java/src/net/i2p/util/ByteCache.java
@@ -13,22 +13,14 @@ import net.i2p.data.ByteArray;
  * Cache the objects frequently used to reduce memory churn.  The ByteArray 
  * should be held onto as long as the  data referenced in it is needed.
  *
+ * For small arrays where the management of valid bytes in ByteArray
+ * and prezeroing isn't required, use SimpleByteArray instead.
+ *
  * Heap size control - survey of usage (April 2010) :
  *
  *  <pre>
 	Size	Max	MaxMem	From
 
-	16	16	256	CryptixAESEngine
-	16	32	512	BloomFilterIVValidator
-	16	64	1K	UDP PacketBuilder
-	16	128	2K	tunnel HopProcessor
-	16	128	2K	tunnel TrivialPreprocessor
-	16	128	2K	tunnel InboundEndpointProcessor
-	16	128	2K	tunnel OutboundGatewayProcessor
-
-	32	64	2K	UDP PacketBuilder
-	32	128	4K	tunnel TrivialPreprocessor
-
 	1K	32	32K	tunnel TrivialPreprocessor
 	1K	512	512K	tunnel FragmentHandler
 	1K	512	512K	I2NP TunnelDataMessage
diff --git a/core/java/src/net/i2p/util/SimpleByteCache.java b/core/java/src/net/i2p/util/SimpleByteCache.java
index 01d116abea1c04eb23fc0d35ab8cce987c15d98d..b41f9ad9b5bf87acedd4aebd7ad8d591b262732f 100644
--- a/core/java/src/net/i2p/util/SimpleByteCache.java
+++ b/core/java/src/net/i2p/util/SimpleByteCache.java
@@ -18,7 +18,7 @@ public final class SimpleByteCache {
 
     private static final Map<Integer, SimpleByteCache> _caches = new ConcurrentHashMap(8);
 
-    private static final int DEFAULT_SIZE = 16;
+    private static final int DEFAULT_SIZE = 64;
 
     /** up to this, use ABQ to minimize object churn and for performance; above this, use LBQ for two locks */
     private static final int MAX_FOR_ABQ = 64;
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
index 8af7c67323d7bc5351179c9d3f0ed9abbc70d945..d6bb57806345e1a0e770aaf0a667e777e2a1599b 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
@@ -16,9 +16,9 @@ import net.i2p.data.Hash;
 import net.i2p.data.RouterIdentity;
 import net.i2p.data.SessionKey;
 import net.i2p.data.Signature;
-import net.i2p.util.ByteCache;
 import net.i2p.util.Addresses;
 import net.i2p.util.Log;
+import net.i2p.util.SimpleByteCache;
 
 /**
  * Big ol' class to do all our packet formatting.  The UDPPackets generated are
@@ -102,9 +102,6 @@ class PacketBuilder {
     private final Log _log;
     private final UDPTransport _transport;
     
-    private static final ByteCache _ivCache = ByteCache.getInstance(64, UDPPacket.IV_SIZE);
-    private static final ByteCache _hmacCache = ByteCache.getInstance(64, Hash.HASH_LENGTH);
-
     /**
      *  For debugging and stats only - does not go out on the wire.
      *  These are chosen to be higher than the highest I2NP message type,
@@ -607,12 +604,12 @@ class PacketBuilder {
         
         // ok, now the full data is in there, but we also need to encrypt
         // the signature, which means we need the IV
-        ByteArray iv = _ivCache.acquire();
-        _context.random().nextBytes(iv.getData());
+        byte[] iv = SimpleByteCache.acquire(UDPPacket.IV_SIZE);
+        _context.random().nextBytes(iv);
         
         int encrWrite = Signature.SIGNATURE_BYTES + 8;
         int sigBegin = off - encrWrite;
-        _context.aes().encrypt(data, sigBegin, data, sigBegin, state.getCipherKey(), iv.getData(), encrWrite);
+        _context.aes().encrypt(data, sigBegin, data, sigBegin, state.getCipherKey(), iv, encrWrite);
         
         // pad up so we're on the encryption boundary
         if ( (off % 16) != 0)
@@ -620,7 +617,7 @@ class PacketBuilder {
         packet.getPacket().setLength(off);
         authenticate(packet, ourIntroKey, ourIntroKey, iv);
         setTo(packet, to, state.getSentPort());
-        _ivCache.release(iv);
+        SimpleByteCache.release(iv);
         packet.setMessageType(TYPE_CREAT);
         return packet;
     }
@@ -1290,10 +1287,10 @@ class PacketBuilder {
      * @param macKey key to generate the, er, MAC
      */
     private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey) {
-        ByteArray iv = _ivCache.acquire();
-        _context.random().nextBytes(iv.getData());
+        byte[] iv = SimpleByteCache.acquire(UDPPacket.IV_SIZE);
+        _context.random().nextBytes(iv);
         authenticate(packet, cipherKey, macKey, iv);
-        _ivCache.release(iv);
+        SimpleByteCache.release(iv);
     }
     
     /**
@@ -1308,38 +1305,38 @@ class PacketBuilder {
      * @param macKey key to generate the, er, MAC
      * @param iv IV to deliver
      */
-    private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey, ByteArray iv) {
+    private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey, byte[] iv) {
         long before = System.currentTimeMillis();
         int encryptOffset = packet.getPacket().getOffset() + UDPPacket.IV_SIZE + UDPPacket.MAC_SIZE;
         int encryptSize = packet.getPacket().getLength() - UDPPacket.IV_SIZE - UDPPacket.MAC_SIZE - packet.getPacket().getOffset();
         byte data[] = packet.getPacket().getData();
-        _context.aes().encrypt(data, encryptOffset, data, encryptOffset, cipherKey, iv.getData(), encryptSize);
+        _context.aes().encrypt(data, encryptOffset, data, encryptOffset, cipherKey, iv, encryptSize);
         
         // ok, now we need to prepare things for the MAC, which requires reordering
         int off = packet.getPacket().getOffset();
         System.arraycopy(data, encryptOffset, data, off, encryptSize);
         off += encryptSize;
-        System.arraycopy(iv.getData(), 0, data, off, UDPPacket.IV_SIZE);
+        System.arraycopy(iv, 0, data, off, UDPPacket.IV_SIZE);
         off += UDPPacket.IV_SIZE;
         DataHelper.toLong(data, off, 2, encryptSize ^ PROTOCOL_VERSION);
         
         int hmacOff = packet.getPacket().getOffset();
         int hmacLen = encryptSize + UDPPacket.IV_SIZE + 2;
         //Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen);
-        ByteArray ba = _hmacCache.acquire();
-        _context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba.getData(), 0);
+        byte[] ba = SimpleByteCache.acquire(Hash.HASH_LENGTH);
+        _context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba, 0);
         
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("Authenticating " + packet.getPacket().getLength() +
-                       "\nIV: " + Base64.encode(iv.getData()) +
-                       "\nraw mac: " + Base64.encode(ba.getData()) +
+                       "\nIV: " + Base64.encode(iv) +
+                       "\nraw mac: " + Base64.encode(ba) +
                        "\nMAC key: " + macKey);
         // ok, now lets put it back where it belongs...
         System.arraycopy(data, hmacOff, data, encryptOffset, encryptSize);
         //System.arraycopy(hmac.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
-        System.arraycopy(ba.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
-        System.arraycopy(iv.getData(), 0, data, hmacOff + UDPPacket.MAC_SIZE, UDPPacket.IV_SIZE);
-        _hmacCache.release(ba);
+        System.arraycopy(ba, 0, data, hmacOff, UDPPacket.MAC_SIZE);
+        System.arraycopy(iv, 0, data, hmacOff + UDPPacket.MAC_SIZE, UDPPacket.IV_SIZE);
+        SimpleByteCache.release(ba);
         long timeToAuth = System.currentTimeMillis() - before;
         _context.statManager().addRateData("udp.packetAuthTime", timeToAuth, timeToAuth);
         if (timeToAuth > 100)
diff --git a/router/java/src/net/i2p/router/tunnel/BloomFilterIVValidator.java b/router/java/src/net/i2p/router/tunnel/BloomFilterIVValidator.java
index 58944818ea120c6da4a91a02fb7847934e5614d8..857c7fdecd846f9988e98bf4901fb5ac73cdf07f 100644
--- a/router/java/src/net/i2p/router/tunnel/BloomFilterIVValidator.java
+++ b/router/java/src/net/i2p/router/tunnel/BloomFilterIVValidator.java
@@ -5,7 +5,7 @@ import net.i2p.data.DataHelper;
 import net.i2p.router.RouterContext;
 import net.i2p.router.util.DecayingBloomFilter;
 import net.i2p.router.util.DecayingHashSet;
-import net.i2p.util.ByteCache;
+import net.i2p.util.SimpleByteCache;
 
 /**
  * Manage the IV validation for all of the router's tunnels by way of a big
@@ -15,7 +15,6 @@ import net.i2p.util.ByteCache;
 class BloomFilterIVValidator implements IVValidator {
     private final RouterContext _context;
     private final DecayingBloomFilter _filter;
-    private final ByteCache _ivXorCache = ByteCache.getInstance(32, HopProcessor.IV_LENGTH);
     
     /**
      * After 2*halflife, an entry is completely forgotten from the bloom filter.
@@ -57,10 +56,10 @@ class BloomFilterIVValidator implements IVValidator {
     }
     
     public boolean receiveIV(byte ivData[], int ivOffset, byte payload[], int payloadOffset) {
-        ByteArray buf = _ivXorCache.acquire();
-        DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf.getData(), 0, HopProcessor.IV_LENGTH);
-        boolean dup = _filter.add(buf.getData()); 
-        _ivXorCache.release(buf);
+        byte[] buf = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
+        DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf, 0, HopProcessor.IV_LENGTH);
+        boolean dup = _filter.add(buf); 
+        SimpleByteCache.release(buf);
         if (dup) _context.statManager().addRateData("tunnel.duplicateIV", 1);
         return !dup; // return true if it is OK, false if it isn't
     }
diff --git a/router/java/src/net/i2p/router/tunnel/HopProcessor.java b/router/java/src/net/i2p/router/tunnel/HopProcessor.java
index 792288a773188ad130cb51a994d8e868235498f9..386f96d798709d6fa41cd90d374b489b69e6dc50 100644
--- a/router/java/src/net/i2p/router/tunnel/HopProcessor.java
+++ b/router/java/src/net/i2p/router/tunnel/HopProcessor.java
@@ -2,7 +2,6 @@ package net.i2p.router.tunnel;
 
 import net.i2p.I2PAppContext;
 import net.i2p.data.Hash;
-import net.i2p.util.ByteCache;
 import net.i2p.util.Log;
 
 /**
@@ -29,7 +28,6 @@ class HopProcessor {
      */
     static final boolean USE_DOUBLE_IV_ENCRYPTION = true;
     static final int IV_LENGTH = 16;
-    private static final ByteCache _cache = ByteCache.getInstance(128, IV_LENGTH);
     
     /** @deprecated unused */
     public HopProcessor(I2PAppContext ctx, HopConfig config) {
diff --git a/router/java/src/net/i2p/router/tunnel/InboundEndpointProcessor.java b/router/java/src/net/i2p/router/tunnel/InboundEndpointProcessor.java
index bd362055b6f8a7af6c18467e9dcd67358132c625..2fd0b26c07ff9792ec12f7ff11ab111d5a85bf5c 100644
--- a/router/java/src/net/i2p/router/tunnel/InboundEndpointProcessor.java
+++ b/router/java/src/net/i2p/router/tunnel/InboundEndpointProcessor.java
@@ -3,8 +3,8 @@ package net.i2p.router.tunnel;
 import net.i2p.data.ByteArray;
 import net.i2p.data.Hash;
 import net.i2p.router.RouterContext;
-import net.i2p.util.ByteCache;
 import net.i2p.util.Log;
+import net.i2p.util.SimpleByteCache;
 
 /**
  * Receive the inbound tunnel message, removing all of the layers
@@ -21,7 +21,6 @@ class InboundEndpointProcessor {
     private final IVValidator _validator;    
     
     static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
-    private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
     
     /** @deprecated unused */
     public InboundEndpointProcessor(RouterContext ctx, TunnelCreatorConfig cfg) {
@@ -54,8 +53,7 @@ class InboundEndpointProcessor {
             return false;
         }
         
-        ByteArray ba = _cache.acquire();
-        byte iv[] = ba.getData(); //new byte[HopProcessor.IV_LENGTH];
+        byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
         System.arraycopy(orig, offset, iv, 0, iv.length);
         //if (_config.getLength() > 1)
         //    _log.debug("IV at inbound endpoint before decrypt: " + Base64.encode(iv));
@@ -64,7 +62,7 @@ class InboundEndpointProcessor {
         if (!ok) {
             if (_log.shouldLog(Log.WARN)) 
                 _log.warn("Invalid IV, dropping at IBEP " + _config);
-            _cache.release(ba);
+            SimpleByteCache.release(iv);
             return false;
         }
         
@@ -72,7 +70,7 @@ class InboundEndpointProcessor {
         if (USE_ENCRYPTION)
             decrypt(_context, _config, iv, orig, offset, length);
         
-        _cache.release(ba);
+        SimpleByteCache.release(iv);
         
         if (_config.getLength() > 0) {
             int rtt = 0; // dunno... may not be related to an rtt
@@ -91,8 +89,7 @@ class InboundEndpointProcessor {
      */
     private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
         //Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
-        ByteArray ba = _cache.acquire();
-        byte cur[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH]; // so we dont malloc
+        byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
         for (int i = cfg.getLength()-2; i >= 0; i--) { // dont include the endpoint, since that is the creator
             OutboundGatewayProcessor.decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
             //if (log.shouldLog(Log.DEBUG)) {
@@ -100,7 +97,7 @@ class InboundEndpointProcessor {
                 //log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
             //}
         }
-        _cache.release(ba);
+        SimpleByteCache.release(cur);
     }
     
 }
diff --git a/router/java/src/net/i2p/router/tunnel/OutboundGatewayProcessor.java b/router/java/src/net/i2p/router/tunnel/OutboundGatewayProcessor.java
index 4deb3bed173881d94f5eaedc7f8a8cd68a522a66..3d86d230ff75b27e70690bfc1c434bcfffcd81aa 100644
--- a/router/java/src/net/i2p/router/tunnel/OutboundGatewayProcessor.java
+++ b/router/java/src/net/i2p/router/tunnel/OutboundGatewayProcessor.java
@@ -3,8 +3,8 @@ package net.i2p.router.tunnel;
 import net.i2p.I2PAppContext;
 import net.i2p.data.Base64;
 import net.i2p.data.ByteArray;
-import net.i2p.util.ByteCache;
 import net.i2p.util.Log;
+import net.i2p.util.SimpleByteCache;
 
 /**
  * Turn the preprocessed tunnel data into something that can be delivered to the
@@ -18,7 +18,6 @@ class OutboundGatewayProcessor {
     private final TunnelCreatorConfig _config;
         
     static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
-    private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
 
     public OutboundGatewayProcessor(I2PAppContext ctx, TunnelCreatorConfig cfg) {
         _context = ctx;
@@ -35,8 +34,7 @@ class OutboundGatewayProcessor {
      * @param length how much of orig can we write to (must be a multiple of 16).
      */
     public void process(byte orig[], int offset, int length) {
-        ByteArray ba = _cache.acquire();
-        byte iv[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH];
+        byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
         //_context.random().nextBytes(iv);
         //System.arraycopy(iv, 0, orig, offset, HopProcessor.IV_LENGTH);
         System.arraycopy(orig, offset, iv, 0, HopProcessor.IV_LENGTH);
@@ -49,7 +47,7 @@ class OutboundGatewayProcessor {
             decrypt(_context, _config, iv, orig, offset, length);
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("finished processing the preprocessed data");
-        _cache.release(ba);
+        SimpleByteCache.release(iv);
     }
     
     /**
@@ -58,8 +56,7 @@ class OutboundGatewayProcessor {
      */
     private void decrypt(I2PAppContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
         Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
-        ByteArray ba = _cache.acquire();
-        byte cur[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH]; // so we dont malloc
+        byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
         for (int i = cfg.getLength()-1; i >= 1; i--) { // dont include hop 0, since that is the creator
             decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
             if (log.shouldLog(Log.DEBUG)) {
@@ -67,7 +64,7 @@ class OutboundGatewayProcessor {
                 //log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
             }
         }
-        _cache.release(ba);
+        SimpleByteCache.release(cur);
     }
     
     /**
diff --git a/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java b/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
index c9655e6873120a1e1a6225ab6d76105592c6fe13..e6edc3c85e35f46fb4cba1d183658c1b211d6ed5 100644
--- a/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
+++ b/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
@@ -9,6 +9,7 @@ import net.i2p.data.Hash;
 import net.i2p.router.RouterContext;
 import net.i2p.util.ByteCache;
 import net.i2p.util.Log;
+import net.i2p.util.SimpleByteCache;
 
 /** 
  * Do the simplest thing possible for preprocessing - for each message available,
@@ -33,9 +34,6 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
      */
     protected static final ByteCache _dataCache = ByteCache.getInstance(32, PREPROCESSED_SIZE);
 
-    private static final ByteCache _ivCache = ByteCache.getInstance(128, IV_SIZE);
-    private static final ByteCache _hashCache = ByteCache.getInstance(128, Hash.HASH_LENGTH);
-    
     public TrivialPreprocessor(RouterContext ctx) {
         _context = ctx;
         _log = ctx.logManager().getLog(getClass());
@@ -63,16 +61,15 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
      * @param fragmentLength fragments[0:fragmentLength] is used
      */
     protected void preprocess(byte fragments[], int fragmentLength) {
-        ByteArray ivBuf = _ivCache.acquire();
-        byte iv[] = ivBuf.getData(); // new byte[IV_SIZE];
+        byte iv[] = SimpleByteCache.acquire(IV_SIZE);
         _context.random().nextBytes(iv);
         
         // payload ready, now H(instructions+payload+IV)
         System.arraycopy(iv, 0, fragments, fragmentLength, IV_SIZE);
         
-        ByteArray hashBuf = _hashCache.acquire();
+        byte[] hashBuf = SimpleByteCache.acquire(Hash.HASH_LENGTH);
         //Hash h = _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE);
-        _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE, hashBuf.getData(), 0);
+        _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE, hashBuf, 0);
         
         //Hash h = _context.sha().calculateHash(target, 0, offset + IV_SIZE);
         //_log.debug("before shift: " + Base64.encode(target));
@@ -91,12 +88,12 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
         System.arraycopy(iv, 0, fragments, offset, IV_SIZE);
         offset += IV_SIZE;
         //System.arraycopy(h.getData(), 0, fragments, offset, 4);
-        System.arraycopy(hashBuf.getData(), 0, fragments, offset, 4);
+        System.arraycopy(hashBuf, 0, fragments, offset, 4);
         offset += 4;
         //_log.debug("before pad  : " + Base64.encode(target));
         
-        _hashCache.release(hashBuf);
-        _ivCache.release(ivBuf);
+        SimpleByteCache.release(hashBuf);
+        SimpleByteCache.release(iv);
         
         // fits in a single message, so may be smaller than the full size
         int numPadBytes = PREPROCESSED_SIZE     // max