jdk/src/share/classes/sun/nio/ch/Util.java
changeset 2 90ce3da70b43
child 51 6fe31bc95bbc
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.ch;
       
    27 
       
    28 import java.lang.ref.SoftReference;
       
    29 import java.lang.reflect.*;
       
    30 import java.io.IOException;
       
    31 import java.nio.ByteBuffer;
       
    32 import java.nio.MappedByteBuffer;
       
    33 import java.nio.channels.*;
       
    34 import java.nio.channels.spi.*;
       
    35 import java.security.AccessController;
       
    36 import java.security.PrivilegedAction;
       
    37 import java.util.*;
       
    38 import sun.misc.Unsafe;
       
    39 import sun.misc.Cleaner;
       
    40 import sun.security.action.GetPropertyAction;
       
    41 
       
    42 
       
    43 class Util {
       
    44 
       
    45 
       
    46     // -- Caches --
       
    47 
       
    48     // The number of temp buffers in our pool
       
    49     private static final int TEMP_BUF_POOL_SIZE = 3;
       
    50 
       
    51     // Per-thread soft cache of the last temporary direct buffer
       
    52     private static ThreadLocal[] bufferPool;
       
    53 
       
    54     static {
       
    55         bufferPool = new ThreadLocal[TEMP_BUF_POOL_SIZE];
       
    56         for (int i=0; i<TEMP_BUF_POOL_SIZE; i++)
       
    57             bufferPool[i] = new ThreadLocal();
       
    58     }
       
    59 
       
    60     static ByteBuffer getTemporaryDirectBuffer(int size) {
       
    61         ByteBuffer buf = null;
       
    62         // Grab a buffer if available
       
    63         for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
       
    64             SoftReference ref = (SoftReference)(bufferPool[i].get());
       
    65             if ((ref != null) && ((buf = (ByteBuffer)ref.get()) != null) &&
       
    66                 (buf.capacity() >= size)) {
       
    67                 buf.rewind();
       
    68                 buf.limit(size);
       
    69                 bufferPool[i].set(null);
       
    70                 return buf;
       
    71             }
       
    72         }
       
    73 
       
    74         // Make a new one
       
    75         return ByteBuffer.allocateDirect(size);
       
    76     }
       
    77 
       
    78     static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
       
    79         if (buf == null)
       
    80             return;
       
    81         // Put it in an empty slot if such exists
       
    82         for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
       
    83             SoftReference ref = (SoftReference)(bufferPool[i].get());
       
    84             if ((ref == null) || (ref.get() == null)) {
       
    85                 bufferPool[i].set(new SoftReference(buf));
       
    86                 return;
       
    87             }
       
    88         }
       
    89         // Otherwise replace a smaller one in the cache if such exists
       
    90         for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
       
    91             SoftReference ref = (SoftReference)(bufferPool[i].get());
       
    92             ByteBuffer inCacheBuf = (ByteBuffer)ref.get();
       
    93             if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) {
       
    94                 bufferPool[i].set(new SoftReference(buf));
       
    95                 return;
       
    96             }
       
    97         }
       
    98     }
       
    99 
       
   100     private static class SelectorWrapper {
       
   101         private Selector sel;
       
   102         private SelectorWrapper (Selector sel) {
       
   103             this.sel = sel;
       
   104             Cleaner.create(this, new Closer(sel));
       
   105         }
       
   106         private static class Closer implements Runnable {
       
   107             private Selector sel;
       
   108             private Closer (Selector sel) {
       
   109                 this.sel = sel;
       
   110             }
       
   111             public void run () {
       
   112                 try {
       
   113                     sel.close();
       
   114                 } catch (Throwable th) {
       
   115                     throw new Error(th);
       
   116                 }
       
   117             }
       
   118         }
       
   119         public Selector get() { return sel;}
       
   120     }
       
   121 
       
   122     // Per-thread cached selector
       
   123     private static ThreadLocal localSelector = new ThreadLocal();
       
   124     // Hold a reference to the selWrapper object to prevent it from
       
   125     // being cleaned when the temporary selector wrapped is on lease.
       
   126     private static ThreadLocal localSelectorWrapper = new ThreadLocal();
       
   127 
       
   128     // When finished, invoker must ensure that selector is empty
       
   129     // by cancelling any related keys and explicitly releasing
       
   130     // the selector by invoking releaseTemporarySelector()
       
   131     static Selector getTemporarySelector(SelectableChannel sc)
       
   132         throws IOException
       
   133     {
       
   134         SoftReference ref = (SoftReference)localSelector.get();
       
   135         SelectorWrapper selWrapper = null;
       
   136         Selector sel = null;
       
   137         if (ref == null
       
   138             || ((selWrapper = (SelectorWrapper) ref.get()) == null)
       
   139             || ((sel = selWrapper.get()) == null)
       
   140             || (sel.provider() != sc.provider())) {
       
   141             sel = sc.provider().openSelector();
       
   142             localSelector.set(new SoftReference(new SelectorWrapper(sel)));
       
   143         } else {
       
   144             localSelectorWrapper.set(selWrapper);
       
   145         }
       
   146         return sel;
       
   147     }
       
   148 
       
   149     static void releaseTemporarySelector(Selector sel)
       
   150         throws IOException
       
   151     {
       
   152         // Selector should be empty
       
   153         sel.selectNow();                // Flush cancelled keys
       
   154         assert sel.keys().isEmpty() : "Temporary selector not empty";
       
   155         localSelectorWrapper.set(null);
       
   156     }
       
   157 
       
   158 
       
   159     // -- Random stuff --
       
   160 
       
   161     static ByteBuffer[] subsequence(ByteBuffer[] bs, int offset, int length) {
       
   162         if ((offset == 0) && (length == bs.length))
       
   163             return bs;
       
   164         int n = length;
       
   165         ByteBuffer[] bs2 = new ByteBuffer[n];
       
   166         for (int i = 0; i < n; i++)
       
   167             bs2[i] = bs[offset + i];
       
   168         return bs2;
       
   169     }
       
   170 
       
   171     static <E> Set<E> ungrowableSet(final Set<E> s) {
       
   172         return new Set<E>() {
       
   173 
       
   174                 public int size()                 { return s.size(); }
       
   175                 public boolean isEmpty()          { return s.isEmpty(); }
       
   176                 public boolean contains(Object o) { return s.contains(o); }
       
   177                 public Object[] toArray()         { return s.toArray(); }
       
   178                 public <T> T[] toArray(T[] a)     { return s.toArray(a); }
       
   179                 public String toString()          { return s.toString(); }
       
   180                 public Iterator<E> iterator()     { return s.iterator(); }
       
   181                 public boolean equals(Object o)   { return s.equals(o); }
       
   182                 public int hashCode()             { return s.hashCode(); }
       
   183                 public void clear()               { s.clear(); }
       
   184                 public boolean remove(Object o)   { return s.remove(o); }
       
   185 
       
   186                 public boolean containsAll(Collection<?> coll) {
       
   187                     return s.containsAll(coll);
       
   188                 }
       
   189                 public boolean removeAll(Collection<?> coll) {
       
   190                     return s.removeAll(coll);
       
   191                 }
       
   192                 public boolean retainAll(Collection<?> coll) {
       
   193                     return s.retainAll(coll);
       
   194                 }
       
   195 
       
   196                 public boolean add(E o){
       
   197                     throw new UnsupportedOperationException();
       
   198                 }
       
   199                 public boolean addAll(Collection<? extends E> coll) {
       
   200                     throw new UnsupportedOperationException();
       
   201                 }
       
   202 
       
   203         };
       
   204     }
       
   205 
       
   206 
       
   207     // -- Unsafe access --
       
   208 
       
   209     private static Unsafe unsafe = Unsafe.getUnsafe();
       
   210 
       
   211     private static byte _get(long a) {
       
   212         return unsafe.getByte(a);
       
   213     }
       
   214 
       
   215     private static void _put(long a, byte b) {
       
   216         unsafe.putByte(a, b);
       
   217     }
       
   218 
       
   219     static void erase(ByteBuffer bb) {
       
   220         unsafe.setMemory(((DirectBuffer)bb).address(), bb.capacity(), (byte)0);
       
   221     }
       
   222 
       
   223     static Unsafe unsafe() {
       
   224         return unsafe;
       
   225     }
       
   226 
       
   227     private static int pageSize = -1;
       
   228 
       
   229     static int pageSize() {
       
   230         if (pageSize == -1)
       
   231             pageSize = unsafe().pageSize();
       
   232         return pageSize;
       
   233     }
       
   234 
       
   235     private static volatile Constructor directByteBufferConstructor = null;
       
   236 
       
   237     private static void initDBBConstructor() {
       
   238         AccessController.doPrivileged(new PrivilegedAction() {
       
   239                 public Object run() {
       
   240                     try {
       
   241                         Class cl = Class.forName("java.nio.DirectByteBuffer");
       
   242                         Constructor ctor = cl.getDeclaredConstructor(
       
   243                             new Class[] { int.class,
       
   244                                           long.class,
       
   245                                           Runnable.class });
       
   246                         ctor.setAccessible(true);
       
   247                         directByteBufferConstructor = ctor;
       
   248                     } catch (ClassNotFoundException x) {
       
   249                         throw new InternalError();
       
   250                     } catch (NoSuchMethodException x) {
       
   251                         throw new InternalError();
       
   252                     } catch (IllegalArgumentException x) {
       
   253                         throw new InternalError();
       
   254                     } catch (ClassCastException x) {
       
   255                         throw new InternalError();
       
   256                     }
       
   257                     return null;
       
   258                 }});
       
   259     }
       
   260 
       
   261     static MappedByteBuffer newMappedByteBuffer(int size, long addr,
       
   262                                                 Runnable unmapper)
       
   263     {
       
   264         MappedByteBuffer dbb;
       
   265         if (directByteBufferConstructor == null)
       
   266             initDBBConstructor();
       
   267         try {
       
   268             dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance(
       
   269               new Object[] { new Integer(size),
       
   270                              new Long(addr),
       
   271                              unmapper });
       
   272         } catch (InstantiationException e) {
       
   273             throw new InternalError();
       
   274         } catch (IllegalAccessException e) {
       
   275             throw new InternalError();
       
   276         } catch (InvocationTargetException e) {
       
   277             throw new InternalError();
       
   278         }
       
   279         return dbb;
       
   280     }
       
   281 
       
   282     private static volatile Constructor directByteBufferRConstructor = null;
       
   283 
       
   284     private static void initDBBRConstructor() {
       
   285         AccessController.doPrivileged(new PrivilegedAction() {
       
   286                 public Object run() {
       
   287                     try {
       
   288                         Class cl = Class.forName("java.nio.DirectByteBufferR");
       
   289                         Constructor ctor = cl.getDeclaredConstructor(
       
   290                             new Class[] { int.class,
       
   291                                           long.class,
       
   292                                           Runnable.class });
       
   293                         ctor.setAccessible(true);
       
   294                         directByteBufferRConstructor = ctor;
       
   295                     } catch (ClassNotFoundException x) {
       
   296                         throw new InternalError();
       
   297                     } catch (NoSuchMethodException x) {
       
   298                         throw new InternalError();
       
   299                     } catch (IllegalArgumentException x) {
       
   300                         throw new InternalError();
       
   301                     } catch (ClassCastException x) {
       
   302                         throw new InternalError();
       
   303                     }
       
   304                     return null;
       
   305                 }});
       
   306     }
       
   307 
       
   308     static MappedByteBuffer newMappedByteBufferR(int size, long addr,
       
   309                                                  Runnable unmapper)
       
   310     {
       
   311         MappedByteBuffer dbb;
       
   312         if (directByteBufferRConstructor == null)
       
   313             initDBBRConstructor();
       
   314         try {
       
   315             dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance(
       
   316               new Object[] { new Integer(size),
       
   317                              new Long(addr),
       
   318                              unmapper });
       
   319         } catch (InstantiationException e) {
       
   320             throw new InternalError();
       
   321         } catch (IllegalAccessException e) {
       
   322             throw new InternalError();
       
   323         } catch (InvocationTargetException e) {
       
   324             throw new InternalError();
       
   325         }
       
   326         return dbb;
       
   327     }
       
   328 
       
   329 
       
   330     // -- Bug compatibility --
       
   331 
       
   332     private static volatile String bugLevel = null;
       
   333 
       
   334     static boolean atBugLevel(String bl) {              // package-private
       
   335         if (bugLevel == null) {
       
   336             if (!sun.misc.VM.isBooted())
       
   337                 return false;
       
   338             String value = AccessController.doPrivileged(
       
   339                 new GetPropertyAction("sun.nio.ch.bugLevel"));
       
   340             bugLevel = (value != null) ? value : "";
       
   341         }
       
   342         return bugLevel.equals(bl);
       
   343     }
       
   344 
       
   345 
       
   346 
       
   347     // -- Initialization --
       
   348 
       
   349     private static boolean loaded = false;
       
   350 
       
   351     static void load() {
       
   352         synchronized (Util.class) {
       
   353             if (loaded)
       
   354                 return;
       
   355             loaded = true;
       
   356             java.security.AccessController
       
   357                 .doPrivileged(new sun.security.action.LoadLibraryAction("net"));
       
   358             java.security.AccessController
       
   359                 .doPrivileged(new sun.security.action.LoadLibraryAction("nio"));
       
   360             // IOUtil must be initialized; Its native methods are called from
       
   361             // other places in native nio code so they must be set up.
       
   362             IOUtil.initIDs();
       
   363         }
       
   364     }
       
   365 
       
   366 }