Reference(T referent, ReferenceQueue queue) { this.queue = queue == null ? ReferenceQueue.NULL : queue; if (referent instanceof Class && noclassgc()) { // We don't do Class gc, so no point in using a weak reference for classes. weakRef = null; strongRef = referent; } else if (referent == null) { weakRef = null; } else { weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference); if (queue != null) { queue.addToActiveList(this); } if (this instanceof Cleaner) { new CleanerGuard(); } } }
/** * Uses internal JDK APIs to allocate a DirectByteBuffer while ignoring the JVM's * MaxDirectMemorySize limit (the default limit is too low and we do not want to require users * to increase it). */ @SuppressWarnings("unchecked") public static ByteBuffer allocateDirectBuffer(int size) { try { Class cls = Class.forName("java.nio.DirectByteBuffer"); Constructor constructor = cls.getDeclaredConstructor(Long.TYPE, Integer.TYPE); constructor.setAccessible(true); Field cleanerField = cls.getDeclaredField("cleaner"); cleanerField.setAccessible(true); final long memory = allocateMemory(size); ByteBuffer buffer = (ByteBuffer) constructor.newInstance(memory, size); Cleaner cleaner = Cleaner.create(buffer, new Runnable() { @Override public void run() { freeMemory(memory); } }); cleanerField.set(buffer, cleaner); return buffer; } catch (Exception e) { throwException(e); } throw new IllegalStateException("unreachable"); }
static boolean disposeDirectBuffer(final ByteBuffer buffer) { return AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override @Nullable public Object run() { try { if (buffer instanceof DirectBuffer) { Cleaner cleaner = ((DirectBuffer)buffer).cleaner(); if (cleaner != null) cleaner.clean(); // Already cleaned otherwise } return null; } catch (Throwable e) { return buffer; } } }) == null; }
/** * The serialization format is big-endian and the first value is the number of tokens * Construct the hashinator from a binary description of the ring. * followed by the token values where each token value consists of the 8-byte position on the ring * and and the 4-byte partition id. All values are signed. * @param configBytes config data * @param cooked compressible wire serialization format if true */ public ElasticHashinator(byte configBytes[], boolean cooked) { Pair<Long, Integer> p = (cooked ? updateCooked(configBytes) : updateRaw(configBytes)); m_tokens = p.getFirst(); m_tokenCount = p.getSecond(); m_cleaner = Cleaner.create(this, new Deallocator(m_tokens, m_tokenCount * 8)); m_configBytes = !cooked ? Suppliers.ofInstance(configBytes) : m_configBytesSupplier; m_cookedBytes = cooked ? Suppliers.ofInstance(configBytes) : m_cookedBytesSupplier; m_tokensMap = Suppliers.memoize(new Supplier<ImmutableSortedMap<Integer, Integer>>() { @Override public ImmutableSortedMap<Integer, Integer> get() { ImmutableSortedMap.Builder<Integer, Integer> builder = ImmutableSortedMap.naturalOrder(); for (int ii = 0; ii < m_tokenCount; ii++) { final long ptr = m_tokens + (ii * 8); final int token = Bits.unsafe.getInt(ptr); final int partition = Bits.unsafe.getInt(ptr + 4); builder.put(token, partition); } return builder.build(); } }); }
/** * Private constructor to initialize a hashinator with known tokens. Used for adding/removing * partitions from existing hashinator. * @param tokens */ private ElasticHashinator(SortedMap<Integer, Integer> tokens) { m_tokensMap = Suppliers.ofInstance(ImmutableSortedMap.copyOf(tokens)); Preconditions.checkArgument(m_tokensMap.get().firstEntry().getKey().equals(Integer.MIN_VALUE)); final int bytes = 8 * tokens.size(); m_tokens = Bits.unsafe.allocateMemory(bytes); trackAllocatedHashinatorBytes(bytes); m_cleaner = Cleaner.create(this, new Deallocator(m_tokens, bytes)); int ii = 0; for (Map.Entry<Integer, Integer> e : tokens.entrySet()) { final long ptr = m_tokens + (ii * 8); Bits.unsafe.putInt(ptr, e.getKey()); Bits.unsafe.putInt(ptr + 4, e.getValue()); ii++; } m_tokenCount = tokens.size(); m_configBytes = m_configBytesSupplier; m_cookedBytes = m_cookedBytesSupplier; }
DirectByteBuffer(int cap) { // package-private super(-1, 0, cap, cap, false); Bits.reserveMemory(cap); int ps = Bits.pageSize(); long base = 0; try { base = unsafe.allocateMemory(cap + ps); } catch (OutOfMemoryError x) { Bits.unreserveMemory(cap); throw x; } unsafe.setMemory(base, cap + ps, (byte) 0); if (base % ps != 0) { // Round up to page boundary address = base + ps - (base & (ps - 1)); } else { address = base; } cleaner = Cleaner.create(this, new Deallocator(base, cap)); }
/** * 分配可能手工进行释放的 ByteBuffer * @param capacity 容量 * @return ByteBuffer 对象 */ protected static ByteBuffer allocateManualReleaseBuffer(int capacity){ try { long address = (TUnsafe.getUnsafe().allocateMemory(capacity)); Deallocator deallocator = new Deallocator(address); ByteBuffer byteBuffer = (ByteBuffer) DIRECT_BYTE_BUFFER_CONSTURCTOR.newInstance(address, capacity, deallocator); Cleaner cleaner = Cleaner.create(byteBuffer, deallocator); cleanerField.set(byteBuffer, cleaner); return byteBuffer; } catch (Exception e) { Logger.error("Create ByteBufferChannel error. ", e); return null; } }
public void run() { for (;;) { Reference r; synchronized (lock) { if (pending != null) { r = pending; pending = r.discovered; r.discovered = null; } else { try { lock.wait(); } catch (InterruptedException x) { } continue; } } // Fast path for cleaners if (r instanceof Cleaner) { ((Cleaner)r).clean(); continue; } ReferenceQueue q = r.queue; if (q != ReferenceQueue.NULL) q.enqueue(r); } }
/** * Attempts to pre-emptively invoke the cleaner method on the given object instead * of waiting for the garbage collector to do it. We do this under Windows because * errors can result if a mapped byte buffer is cleaned after its associated file * is closed, truncated, deleted, etc. * @param buffer The buffer to release. */ private static void clean(final Object buffer) { if (buffer != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { try { Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]); getCleanerMethod.setAccessible(true); Cleaner cleaner = (Cleaner)getCleanerMethod.invoke(buffer, new Object[0]); cleaner.clean(); } catch (Exception e) { logger.warn("Error cleaning buffer", e); } return null; } }); } }
protected void init(String file, long length, boolean clearFile) throws Exception { File f = new File(file); if ( f.exists() && clearFile ) { f.delete(); } this.file = f; if ( f.exists() ) { length = f.length(); } RandomAccessFile raf = new RandomAccessFile(f, "rw"); raf.setLength(length); // FIXME: see stackoverflow. does not work always FileChannel fileChannel = raf.getChannel(); this.fileChannel = raf.getChannel(); this.baseAdress = map0(fileChannel, imodeFor(FileChannel.MapMode.READ_WRITE), 0L, length); this.length = length; this.cleaner = Cleaner.create(this, new Unmapper(baseAdress, length, fileChannel)); }
public void shutdown() { removeMonitoring(); writeQ.clear(); readQ.clear(); inputQueue.clear(); try { // Cleanup the ByteBuffers only if they are sun.nio.ch.DirectBuffer // If we don't cleanup then we will leak 16K of memory if (getRbuf() instanceof DirectBuffer) { Cleaner cleaner = ((DirectBuffer) getRbuf()).cleaner(); if (cleaner != null) cleaner.clean(); cleaner = ((DirectBuffer) getWbuf()).cleaner(); if (cleaner != null) cleaner.clean(); } } catch (Throwable t) { getLogger().error("Exception cleaning ByteBuffer.", t); } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public FloatLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.FLOAT; this.sizeof = 4; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new float[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public LongLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.LONG; this.sizeof = 8; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new long[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public IntLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.INT; this.sizeof = 4; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new int[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public ByteLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.BYTE; this.sizeof = 1; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new byte[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public ShortLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.SHORT; this.sizeof = 2; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new short[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public DoubleLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.DOUBLE; this.sizeof = 8; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new double[(int) length]; } }
/** * Creates new instance of this class. * * @param length number of elements * @param zeroNativeMemory if true, then the native memory is zeroed. */ public LogicLargeArray(long length, boolean zeroNativeMemory) { this.type = LargeArrayType.LOGIC; this.sizeof = 1; if (length <= 0) { throw new IllegalArgumentException(length + " is not a positive long value"); } this.length = length; if (length > LARGEST_32BIT_INDEX) { System.gc(); this.ptr = Utilities.UNSAFE.allocateMemory(this.length * this.sizeof); if (zeroNativeMemory) { zeroNativeMemory(length); } Cleaner.create(this, new LargeArray.Deallocator(this.ptr, this.length, this.sizeof)); MemoryCounter.increaseCounter(this.length * this.sizeof); } else { data = new byte[(int) length]; } }
private void close(RandomAccessFile file, Channel channel, MappedByteBuffer mappedFile) { if (mappedFile == null) { return; } // sync to disk mappedFile.force(); try { // close mappedFile AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { Method cleaner = mappedFile.getClass().getMethod("cleaner"); cleaner.setAccessible(true); ((Cleaner) cleaner.invoke(mappedFile)).clean(); return null; }); // close channel if (channel != null && channel.isOpen()) { channel.close(); } // close file if (file != null) { file.close(); } } catch (Exception e) { logger.error(e.getMessage()); e.printStackTrace(); } }
@Override public void close() throws IOException { channel.close(); if (PlatformUtil.IS_WINDOWS) { final Cleaner cleaner = ((DirectBuffer) this.buffer).cleaner(); if (cleaner != null) { cleaner.clean(); } } }
DirectByteBuffer(int cap) { // package-private super(-1, 0, cap, cap); boolean pa = VM.isDirectMemoryPageAligned(); int ps = Bits.pageSize(); long size = Math.max(1L, (long)cap + (pa ? ps : 0)); Bits.reserveMemory(size, cap); long base = 0; try { base = unsafe.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.unreserveMemory(size, cap); throw x; } unsafe.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); } else { address = base; } cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); att = null; }
protected void finalize() { if (isActive()) { cli.System.GC.ReRegisterForFinalize(this); } else { ((Cleaner)Reference.this).clean(); } }
/** * 释放Buffer * 如果因为SecurityManager机制导致Cleaner无法获取, clean方法将无法执行 * * @param byteBuffer buffer */ static public void releaseBuffer(ByteBuffer byteBuffer) { // 是否是directBuffer if (byteBuffer != null && byteBuffer.isDirect()) { Object cleaner = ((DirectBuffer) byteBuffer).cleaner(); if (cleaner != null) ((Cleaner) cleaner).clean(); } }
public static long allocateMemory(long size, Object holder) { final long address = _UNSAFE.allocateMemory(size); Cleaner.create(holder, new Runnable() { @Override public void run() { _UNSAFE.freeMemory(address); } }); return address; }
public AbstractOffheapArray(long capacity) { if (capacity < 0) { throw new IllegalArgumentException("Cannot allocate with capacity=" + capacity); } address = UNSAFE.allocateMemory(capacity); boxedAddress = new AtomicLong(address); cleaner = Cleaner.create(this, new Deallocator(boxedAddress)); UNSAFE.setMemory(address, capacity, (byte) 0); this.capacity = capacity; }
private MappedFile(RandomAccessFile raf, long size) { this.raf = raf; this.size = pageAlign(size); this.channel = raf.getChannel(); this.address = map(); this.cleaner = Cleaner.create(this, new Deallocator()); }
public static void free(ByteBuffer buffer) { if (buffer.isDirect()) { Cleaner cleaner = ((DirectBuffer) buffer).cleaner(); if (cleaner != null) { cleaner.clean(); } } }
public static ByteBuffer getByteBuffer(long address, int length, boolean autoFree) { ByteBuffer instance = getHollowDirectByteBuffer(); if (autoFree) { Cleaner cleaner = Cleaner.create(instance, new Deallocator(address)); setByteBuffer(instance, address, length, cleaner); } else { setByteBuffer(instance, address, length, null); } instance.order(ByteOrder.nativeOrder()); return instance; }
public static void setByteBuffer(ByteBuffer instance, long address, int length, Cleaner cleaner) { unsafe.putLong(instance, DIRECT_BYTE_BUFFER_ADDRESS_OFFSET, address); unsafe.putInt(instance, DIRECT_BYTE_BUFFER_CAPACITY_OFFSET, length); unsafe.putInt(instance, DIRECT_BYTE_BUFFER_LIMIT_OFFSET, length); if (cleaner != null) { unsafe.putObject(instance, DIRECT_BYTE_BUFFER_CLEANER, cleaner); } }
private void clean(MappedByteBuffer mapping) { if (mapping == null) { return; } Cleaner cleaner = ((DirectBuffer) mapping).cleaner(); if (cleaner != null) { cleaner.clean(); } }
static void freeDirectBuffer(ByteBuffer buffer) { if (CLEANER_FIELD_OFFSET == -1 || !buffer.isDirect()) { return; } try { Cleaner cleaner = (Cleaner) PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET); if (cleaner != null) { cleaner.clean(); } } catch (Throwable t) { // Nothing we can do here. } }
/*** * Release a direct buffer. * * NOTE: If Cleaner is not accessible due to SecurityManager restrictions, reflection could be used * to obtain the "clean" method and then invoke it. */ static public void releaseBuffer(ByteBuffer niobuffer) { if(niobuffer != null && niobuffer.isDirect()) { Object cleaner = ((DirectBuffer) niobuffer).cleaner(); if(cleaner != null) ((Cleaner)cleaner).clean(); niobuffer = null; } }
public void run() { for (;;) { Reference r; synchronized (lock) { if (pending != null) { r = pending; Reference rn = r.next; pending = (rn == r) ? null : rn; r.next = r; } else { try { lock.wait(); } catch (InterruptedException x) { } continue; } } // Fast path for cleaners if (r instanceof Cleaner) { ((Cleaner)r).clean(); continue; } ReferenceQueue q = r.queue; if (q != ReferenceQueue.NULL) q.enqueue(r); } }
protected DirectBitBuffer(long bits){ long bytes = (long) Math.ceil(bits / 8.d); try { address = unsafe.allocateMemory(bytes); } catch (OutOfMemoryError ex) { throw ex; } Deallocator dall = new Deallocator(address); dealloc = dall; finalizer = Cleaner.create(this,dall);//point finalizer to this object unsafe.setMemory(address,bytes,(byte)0); size = bytes; }