1 package com.sun.nio.ch;
   2 
   3 import jdk.internal.ref.Cleaner;
   4 import sun.nio.ch.DirectBuffer;
   5 
   6 import java.nio.ByteBuffer;
   7 import java.nio.channels.FileChannel;
   8 import java.security.Permission;
   9 
  10 /**
  11  * A utility to deallocate native memory retained by direct byte buffers.
  12  *
  13  * @since 9
  14  */
  15 public final class DirectBufferDeallocator {
  16 
  17     private static final Permission PERMISSION =
  18         new RuntimePermission("directBufferDeallocatorAccess");
  19 
  20     /**
  21      * Constructs a {@code DirectBufferDeallocator} which can be used to
  22      * {@link #deallocate} direct memory retained by
  23      * {@link ByteBuffer#isDirect() direct} {@code ByteBuffer}s.
  24      * <p> First, if there is a security manager, its {@code checkPermission}
  25      * method is called with a {@link java.lang.RuntimePermission} with target
  26      * {@code "directBufferDeallocatorAccess"}.  This may result in a security
  27      * exception.
  28      * <p> The returned {@code DirectBufferDeallocator} object should be carefully
  29      * guarded by the caller, since it can be used to deallocate native memory
  30      * used by direct buffers while access to it is still being performed
  31      * and consequently jeopardise the stability of the VM process as a whole.
  32      *
  33      * @return the DirectBufferDeallocator
  34      * @throws SecurityException if a security manager exists and its
  35      *                           {@code checkPermission} method doesn't allow
  36      *                           access to the RuntimePermission
  37      *                           "directBufferDeallocatorAccess".
  38      */
  39     public DirectBufferDeallocator() {
  40         SecurityManager security = System.getSecurityManager();
  41         if (security != null)
  42             security.checkPermission(PERMISSION);
  43     }
  44 
  45     /**
  46      * If given {@code buffer} is a {@link ByteBuffer#isDirect() direct}
  47      * {@code ByteBuffer} obtained by invoking
  48      * {@link ByteBuffer#allocateDirect} or {@link FileChannel#map} methods,
  49      * native memory retained by it is deallocated or unmapped.
  50      * Otherwise if given {@code buffer} is not a direct buffer or has been
  51      * obtained by {@link ByteBuffer#duplicate() duplicating} or
  52      * {@link ByteBuffer#slice(int, int) slicing} a direct buffer,
  53      * then this method does nothing.
  54      *
  55      * @param buffer a {@code ByteBuffer} which's native memory is to be
  56      *               deallocated.
  57      */
  58     public void deallocate(ByteBuffer buffer) {
  59         if (buffer.isDirect()) {
  60             Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
  61             if (cleaner != null) {
  62                 cleaner.clean();
  63             }
  64         }
  65     }
  66 }