diff --git a/core/java/src/net/i2p/data/ByteArray.java b/core/java/src/net/i2p/data/ByteArray.java index 9f460fe475..d013809c8e 100644 --- a/core/java/src/net/i2p/data/ByteArray.java +++ b/core/java/src/net/i2p/data/ByteArray.java @@ -24,11 +24,21 @@ public class ByteArray implements Serializable, Comparable { public ByteArray() { } - /** Sets valid */ + /** + * Sets valid = data.length, unless data is null + * Sets offset = 0 + * @param data may be null + */ public ByteArray(byte[] data) { _data = data; _valid = (data != null ? data.length : 0); } + + /** + * Sets offset = offset + * Sets valid = length + * @param data may be null but why would you do that + */ public ByteArray(byte[] data, int offset, int length) { _data = data; _offset = offset; diff --git a/core/java/src/net/i2p/util/ByteCache.java b/core/java/src/net/i2p/util/ByteCache.java index 7253a472e8..b88a21c141 100644 --- a/core/java/src/net/i2p/util/ByteCache.java +++ b/core/java/src/net/i2p/util/ByteCache.java @@ -16,7 +16,7 @@ import net.i2p.data.ByteArray; * 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) : + * Heap size control - survey of usage: * *
Size Max MaxMem From @@ -34,6 +34,8 @@ import net.i2p.data.ByteArray; 8K 8 64K I2PTunnel HTTPResponseOutputStream + 16K 16 256K I2PSnark + 32K 4 128K SAM StreamSession 32K 10 320K SAM v2StreamSession 32K 64 2M UDP OMS @@ -67,7 +69,10 @@ public final class ByteCache { } /** - * Get a cache responsible for objects of the given size + * Get a cache responsible for objects of the given size. + * Warning, if you store the result in a static field, the cleaners will + * not operate after a restart on Android, as the old context's SimpleScheduler will have shut down. + * TODO tie this to the context or clean up all calls. * * @param cacheSize how large we want the cache to grow * (number of objects, NOT memory size) @@ -103,7 +108,7 @@ public final class ByteCache { /** list of available and available entries */ private Queue_available; private int _maxCached; - private int _entrySize; + private final int _entrySize; private long _lastOverflow; /** do we actually want to cache? Warning - setting to false may NPE, this should be fixed or removed */ @@ -120,7 +125,7 @@ public final class ByteCache { _maxCached = maxCachedEntries; _entrySize = entrySize; _lastOverflow = -1; - SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY + (entrySize % 7)); //stagger + SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY + (entrySize % 777)); //stagger I2PAppContext.getGlobalContext().statManager().createRateStat("byteCache.memory." + entrySize, "Memory usage (B)", "Router", new long[] { 10*60*1000 }); } @@ -136,8 +141,11 @@ public final class ByteCache { } /** - * Get the next available structure, either from the cache or a brand new one - * + * Get the next available structure, either from the cache or a brand new one. + * Returned ByteArray will have valid = 0 and offset = 0. + * Returned ByteArray may or may not be zero, depends on whether + * release(ba) or release(ba, false) was called. + * Which is a problem, you should really specify shouldZero on acquire, not release. */ public final ByteArray acquire() { if (_cache) { @@ -149,7 +157,7 @@ public final class ByteCache { byte data[] = new byte[_entrySize]; ByteArray rv = new ByteArray(data); rv.setValid(0); - rv.setOffset(0); + //rv.setOffset(0); return rv; } @@ -160,11 +168,17 @@ public final class ByteCache { public final void release(ByteArray entry) { release(entry, true); } + public final void release(ByteArray entry, boolean shouldZero) { if (_cache) { - if ( (entry == null) || (entry.getData() == null) ) + if (entry == null || entry.getData() == null) return; - + if (entry.getData().length != _entrySize) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class); + if (log.shouldLog(Log.WARN)) + log.warn("Bad size", new Exception("I did it")); + return; + } entry.setValid(0); entry.setOffset(0);