package org.kne.cloud.network; import java.lang.ref.Cleaner; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import org.kne.debug.TimeDebugger; public class ByteBufferAllocator { private List bbfps=new ArrayList<>(); private ByteBufferPool[]bbfpsarr; private ReferenceQueue refq=new ReferenceQueue<>(); private boolean isDirect; public ByteBufferAllocator(boolean isDirect) { this.isDirect=isDirect; int i=1; int maxi=0; int mps=16; for (int j = 0; j < 18; j++) { int count=100; mps+=count; bbfps.add(new ByteBufferPool(mps, i,isDirect)); maxi=i; i<<=1; } bbfpsarr=new ByteBufferPool[maxi]; for (int j = 0; j < bbfpsarr.length; j++) { bbfpsarr[j]=getByteBufferPool(j); } Thread t= new Thread(()->{ while(true) { try { Reference ref; ref = refq.remove(); if(ref!=null) { ref.clear(); } } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }); t.setPriority(Thread.MAX_PRIORITY-1); t.start(); } public ByteBuffer allocate(int capacity) { if(true) { return allocateHeap(capacity); } //new Exception().printStackTrace(); ByteBufferPool bbfp=bbfpsarr[capacity]; ByteBuffer bbf=null; try { bbf=bbfp.borrow(); }catch(OutOfMemoryError err) { System.gc(); Thread.yield(); bbf=bbfp.borrow(); } ByteBuffer bbfs=bbf.slice(0, capacity); new ByteBufferPhantomReference(bbfs,refq,bbf,bbfp); return bbfs; } private static ByteBuffer allocateHeap(int capacity) { return ByteBuffer.wrap(new byte[capacity]); } private ByteBufferPool getByteBufferPool(int capacity) { int elen=0; for (int i = 0; i < bbfps.size(); i++) { ByteBufferPool bfp=bbfps.get(i); if(capacity<=(elen= bfp.getLength())) { return bfp; } } throw new RuntimeException("capacity:"+capacity+">"+elen); } private static class ByteBufferPhantomReference extends PhantomReference{ private static AtomicReference first=new AtomicReference<>(null); private AtomicReference next=new AtomicReference<>(null); private AtomicReference prev=new AtomicReference<>(null); private ByteBuffer father; private ByteBufferPool pool; public ByteBufferPhantomReference(ByteBuffer referent, ReferenceQueue q,ByteBuffer father,ByteBufferPool pool) { super(referent, q); this.father=father; this.pool=pool; insert(); } private void insert() { ByteBufferPhantomReference refn= first.getAndSet(this); if(refn!=null) { next.set(refn); refn.prev.set(this); } } private void remove() { ByteBufferPhantomReference prevn= prev.getAndSet(null); ByteBufferPhantomReference nextn=next.getAndSet(null); if(prevn!=null) prevn.next.set(nextn); if(nextn!=null) nextn.prev.set(prevn); } @Override public void clear() { //System.out.println("clear"); pool.back(father); remove(); super.clear(); } } }