📄 directbytebufferpoolreal.java
字号:
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space
// Source File Name: DirectByteBufferPoolReal.java
package org.gudy.azureus2.core3.util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.logging.LogAlert;
import org.gudy.azureus2.core3.logging.Logger;
// Referenced classes of package org.gudy.azureus2.core3.util:
// DirectByteBufferPool, Debug, DirectByteBuffer, SimpleTimer,
// TimerEventPerformer, TimerEvent
public class DirectByteBufferPoolReal extends DirectByteBufferPool
{
private static class myInteger
{
int value;
private myInteger()
{
}
}
private static class sliceBuffer
{
private ByteBuffer buffer;
private short alloc_id;
private short slice_id;
protected ByteBuffer getBuffer()
{
return buffer;
}
protected short getAllocID()
{
return alloc_id;
}
protected short getSliceID()
{
return slice_id;
}
protected sliceBuffer(ByteBuffer _buffer, short _alloc_id, short _slice_id)
{
buffer = _buffer;
alloc_id = _alloc_id;
slice_id = _slice_id;
}
}
private static class sliceDBB extends DirectByteBuffer
{
private sliceBuffer slice_buffer;
protected sliceBuffer getSliceBuffer()
{
return slice_buffer;
}
protected sliceDBB(byte _allocator, sliceBuffer _sb)
{
super(_allocator, _sb.getBuffer(), DirectByteBufferPoolReal.pool);
slice_buffer = _sb;
}
}
protected static final boolean DEBUG_TRACK_HANDEDOUT = false;
protected static final boolean DEBUG_PRINT_MEM = false;
protected static final int DEBUG_PRINT_TIME = 0x1d4c0;
protected static final boolean DEBUG_HANDOUT_SIZES = false;
protected static final boolean DEBUG_FREE_SIZES = false;
private static final int START_POWER = 12;
private static final int END_POWER = 25;
private static final int EXTRA_BUCKETS[] = {
16512
};
public static final int MAX_SIZE = BigInteger.valueOf(2L).pow(25).intValue();
private static final DirectByteBufferPoolReal pool = new DirectByteBufferPoolReal();
private final Map buffersMap = new LinkedHashMap(14);
private final Object poolsLock = new Object();
private static final int SLICE_END_SIZE = 2048;
private static final int SLICE_ALLOC_CHUNK_SIZE = 4096;
private static final short SLICE_ENTRY_SIZES[] = {
8, 16, 32, 64, 128, 256, 512, 1024, 2048
};
private static final short SLICE_ALLOC_MAXS[] = {
256, 256, 128, 64, 64, 64, 64, 64, 64
};
private static final short SLICE_ENTRY_ALLOC_SIZES[];
private static final List slice_entries[];
private static final boolean slice_allocs[][];
private static final boolean slice_alloc_fails[] = new boolean[SLICE_ENTRY_SIZES.length];
private static final long slice_use_count[] = new long[SLICE_ENTRY_SIZES.length];
private final Map handed_out = new IdentityHashMap();
private final Map size_counts = new TreeMap();
private static final long COMPACTION_CHECK_PERIOD = 0x1d4c0L;
private static final long MAX_FREE_BYTES = 0xa00000L;
private static final long MIN_FREE_BYTES = 0x100000L;
private long bytesIn;
private long bytesOut;
protected DirectByteBufferPoolReal()
{
bytesIn = 0L;
bytesOut = 0L;
ArrayList list = new ArrayList();
for (int p = 12; p <= 25; p++)
list.add(new Integer(BigInteger.valueOf(2L).pow(p).intValue()));
for (int i = 0; i < EXTRA_BUCKETS.length; i++)
list.add(new Integer(EXTRA_BUCKETS[i]));
Integer sizes[] = new Integer[list.size()];
list.toArray(sizes);
Arrays.sort(sizes);
for (int i = 0; i < sizes.length; i++)
{
ArrayList bufferPool = new ArrayList();
buffersMap.put(sizes[i], bufferPool);
}
SimpleTimer.addPeriodicEvent("DirectBB:compact", 0x1d4c0L, new TimerEventPerformer() {
final DirectByteBufferPoolReal this$0;
public void perform(TimerEvent ev)
{
compactBuffers();
}
{
this$0 = DirectByteBufferPoolReal.this;
super();
}
});
}
private ByteBuffer allocateNewBuffer(int _size)
{
return ByteBuffer.allocateDirect(_size);
OutOfMemoryError e;
e;
clearBufferPools();
runGarbageCollection();
return ByteBuffer.allocateDirect(_size);
OutOfMemoryError ex;
ex;
String msg = "Memory allocation failed: Out of direct memory space.\nTo fix: Use the -XX:MaxDirectMemorySize=512m command line option,\nor upgrade your Java JRE to version 1.4.2_05 or 1.5 series or newer.";
Debug.out(msg);
Logger.log(new LogAlert(false, 3, msg));
printInUse(true);
throw ex;
}
protected DirectByteBuffer getBufferSupport(byte _allocator, int _length)
{
if (_length < 1)
{
Debug.out((new StringBuilder()).append("requested length [").append(_length).append("] < 1").toString());
return null;
}
if (_length > MAX_SIZE)
{
Debug.out((new StringBuilder()).append("requested length [").append(_length).append("] > MAX_SIZE [").append(MAX_SIZE).append("]").toString());
return null;
} else
{
return pool.getBufferHelper(_allocator, _length);
}
}
private DirectByteBuffer getBufferHelper(byte _allocator, int _length)
{
DirectByteBuffer res;
ByteBuffer buff;
if (_length <= 2048)
{
res = getSliceBuffer(_allocator, _length);
} else
{
buff = null;
Integer reqVal = new Integer(_length);
Iterator it = buffersMap.keySet().iterator();
do
{
if (!it.hasNext())
break;
Integer keyVal = (Integer)it.next();
if (reqVal.compareTo(keyVal) > 0)
continue;
ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
synchronized (poolsLock)
{
if (bufferPool.isEmpty())
buff = allocateNewBuffer(keyVal.intValue());
else
synchronized (bufferPool)
{
buff = (ByteBuffer)bufferPool.remove(bufferPool.size() - 1);
}
}
break;
} while (true);
if (buff == null)
{
Debug.out("Unable to find an appropriate buffer pool");
throw new RuntimeException("Unable to find an appropriate buffer pool");
}
res = new DirectByteBuffer(_allocator, buff, this);
}
buff = res.getBufferInternal();
buff.clear();
buff.limit(_length);
bytesOut += buff.capacity();
return res;
}
protected void returnBufferSupport(DirectByteBuffer ddb)
{
ByteBuffer buff = ddb.getBufferInternal();
int capacity = buff.capacity();
bytesIn += capacity;
if (capacity <= 2048)
{
freeSliceBuffer(ddb);
} else
{
Integer buffSize = new Integer(capacity);
ArrayList bufferPool = (ArrayList)buffersMap.get(buffSize);
if (bufferPool != null)
synchronized (bufferPool)
{
bufferPool.add(buff);
}
else
Debug.out("Invalid buffer given; could not find proper buffer pool");
}
}
private void clearBufferPools()
{
ArrayList bufferPool;
for (Iterator it = buffersMap.values().iterator(); it.hasNext(); bufferPool.clear())
bufferPool = (ArrayList)it.next();
}
private void runGarbageCollection()
{
System.runFinalization();
System.gc();
}
private void compactBuffers()
{
long freeSize;
label0:
{
synchronized (poolsLock)
{
freeSize = bytesFree();
if (freeSize >= 0x100000L)
break label0;
}
break MISSING_BLOCK_LABEL_163;
}
float remainingFactor;
if (freeSize > 0xa00000L)
remainingFactor = 5242880F / (float)freeSize;
else
remainingFactor = 1.0F - (0.5F * (float)freeSize) / 1.048576E+007F;
ArrayList pools = new ArrayList(buffersMap.values());
for (int i = pools.size() - 1; i >= 0; i--)
{
ArrayList pool = (ArrayList)pools.get(i);
int limit = (int)((float)pool.size() * remainingFactor);
for (int j = pool.size() - 1; j >= limit; j--)
pool.remove(j);
}
runGarbageCollection();
obj;
JVM INSTR monitorexit ;
break MISSING_BLOCK_LABEL_163;
exception;
throw exception;
compactSlices();
return;
}
private long bytesFree()
{
long bytesUsed = 0L;
synchronized (poolsLock)
{
for (Iterator it = buffersMap.keySet().iterator(); it.hasNext();)
{
Integer keyVal = (Integer)it.next();
ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
bytesUsed += keyVal.intValue() * bufferPool.size();
}
}
return bytesUsed;
}
private void printInUse(boolean flag)
{
}
private DirectByteBuffer getSliceBuffer(byte _allocator, int _length)
{
int slice_index = getSliceIndex(_length);
List my_slice_entries = slice_entries[slice_index];
List list = my_slice_entries;
JVM INSTR monitorenter ;
sliceBuffer sb;
ByteBuffer buff;
boolean my_allocs[] = slice_allocs[slice_index];
sb = null;
if (my_slice_entries.size() > 0)
{
sb = (sliceBuffer)my_slice_entries.remove(0);
slice_use_count[slice_index]++;
break MISSING_BLOCK_LABEL_305;
}
short slot = -1;
short i = 0;
do
{
if (i >= my_allocs.length)
break;
if (!my_allocs[i])
{
slot = i;
break;
}
i++;
} while (true);
if (slot != -1)
{
short slice_entry_size = SLICE_ENTRY_SIZES[slice_index];
short slice_entry_count = SLICE_ENTRY_ALLOC_SIZES[slice_index];
ByteBuffer chunk = ByteBuffer.allocateDirect(slice_entry_size * slice_entry_count);
my_allocs[slot] = true;
for (short i = 0; i < slice_entry_count; i++)
{
chunk.limit((i + 1) * slice_entry_size);
chunk.position(i * slice_entry_size);
ByteBuffer slice = chunk.slice();
sliceBuffer new_buffer = new sliceBuffer(slice, slot, i);
if (i == 0)
{
sb = new_buffer;
slice_use_count[slice_index]++;
} else
{
my_slice_entries.add(new_buffer);
}
}
break MISSING_BLOCK_LABEL_305;
}
if (!slice_alloc_fails[slice_index])
{
slice_alloc_fails[slice_index] = true;
Debug.out((new StringBuilder()).append("Run out of slice space for '").append(SLICE_ENTRY_SIZES[slice_index]).append(", reverting to normal allocation").toString());
}
buff = ByteBuffer.allocate(_length);
return new DirectByteBuffer(_allocator, buff, this);
sliceDBB dbb = new sliceDBB(_allocator, sb);
dbb;
list;
JVM INSTR monitorexit ;
return;
Exception exception;
exception;
throw exception;
}
private void freeSliceBuffer(DirectByteBuffer ddb)
{
if (ddb instanceof sliceDBB)
{
int slice_index = getSliceIndex(ddb.getBufferInternal().capacity());
List my_slice_entries = slice_entries[slice_index];
synchronized (my_slice_entries)
{
my_slice_entries.add(0, ((sliceDBB)ddb).getSliceBuffer());
}
}
}
private void compactSlices()
{
for (int i = 0; i < slice_entries.length; i++)
{
int entries_per_alloc = SLICE_ENTRY_ALLOC_SIZES[i];
List l = slice_entries[i];
if (l.size() < entries_per_alloc)
continue;
synchronized (l)
{
Collections.sort(l, new Comparator() {
final DirectByteBufferPoolReal this$0;
public int compare(Object o1, Object o2)
{
sliceBuffer sb1 = (sliceBuffer)o1;
sliceBuffer sb2 = (sliceBuffer)o2;
int res = sb1.getAllocID() - sb2.getAllocID();
if (res == 0)
res = sb1.getSliceID() - sb2.getSliceID();
return res;
}
{
this$0 = DirectByteBufferPoolReal.this;
super();
}
});
boolean allocs[] = slice_allocs[i];
Iterator it = l.iterator();
int current_alloc = -1;
int entry_count = 0;
boolean freed_one = false;
while (it.hasNext())
{
sliceBuffer sb = (sliceBuffer)it.next();
int aid = sb.getAllocID();
if (aid != current_alloc)
{
if (entry_count == entries_per_alloc)
{
freed_one = true;
allocs[aid] = false;
}
current_alloc = aid;
entry_count = 1;
} else
{
entry_count++;
}
}
if (entry_count == entries_per_alloc)
{
freed_one = true;
allocs[current_alloc] = false;
}
if (freed_one)
{
it = l.iterator();
do
{
if (!it.hasNext())
break;
sliceBuffer sb = (sliceBuffer)it.next();
if (!allocs[sb.getAllocID()])
it.remove();
} while (true);
}
}
}
}
private int getSliceIndex(int _length)
{
for (int i = 0; i < SLICE_ENTRY_SIZES.length; i++)
if (_length <= SLICE_ENTRY_SIZES[i])
return i;
Debug.out("eh?");
return 0;
}
static
{
SLICE_ENTRY_ALLOC_SIZES = new short[SLICE_ENTRY_SIZES.length];
slice_entries = new List[SLICE_ENTRY_SIZES.length];
slice_allocs = new boolean[SLICE_ENTRY_SIZES.length][];
int mult = COConfigurationManager.getIntParameter("memory.slice.limit.multiplier");
if (mult > 1)
{
for (int i = 0; i < SLICE_ALLOC_MAXS.length; i++)
SLICE_ALLOC_MAXS[i] *= mult;
}
for (int i = 0; i < SLICE_ENTRY_SIZES.length; i++)
{
SLICE_ENTRY_ALLOC_SIZES[i] = (short)(4096 / SLICE_ENTRY_SIZES[i]);
slice_allocs[i] = new boolean[SLICE_ALLOC_MAXS[i]];
slice_entries[i] = new LinkedList();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -