< prev index next >

src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

Print this page

        

@@ -864,40 +864,29 @@
     }
 
 
     // -- Memory-mapped buffers --
 
-    private static class Unmapper
+    private static abstract class Unmapper
         implements Runnable
     {
         // may be required to close file
         private static final NativeDispatcher nd = new FileDispatcherImpl();
 
-        // keep track of mapped buffer usage
-        static volatile int count;
-        static volatile long totalSize;
-        static volatile long totalCapacity;
-
         private volatile long address;
-        private final long size;
-        private final int cap;
+        protected final long size;
+        protected final int cap;
         private final FileDescriptor fd;
 
         private Unmapper(long address, long size, int cap,
                          FileDescriptor fd)
         {
             assert (address != 0);
             this.address = address;
             this.size = size;
             this.cap = cap;
             this.fd = fd;
-
-            synchronized (Unmapper.class) {
-                count++;
-                totalSize += size;
-                totalCapacity += cap;
-            }
         }
 
         public void run() {
             if (address == 0)
                 return;

@@ -911,11 +900,67 @@
                 } catch (IOException ignore) {
                     // nothing we can do
                 }
             }
 
-            synchronized (Unmapper.class) {
+            decrement_stats();
+        }
+        protected abstract void increment_stats();
+        protected abstract void decrement_stats();
+    }
+
+    private static class DefaultUnmapper extends Unmapper {
+
+        // keep track of non-persistent mapped buffer usage
+        static volatile int count;
+        static volatile long totalSize;
+        static volatile long totalCapacity;
+
+        public DefaultUnmapper(long address, long size, int cap,
+                                     FileDescriptor fd) {
+            super(address, size, cap, fd);
+            increment_stats();
+        }
+        
+        protected void increment_stats() {
+            synchronized (DefaultUnmapper.class) {
+                count++;
+                totalSize += size;
+                totalCapacity += cap;
+            }
+        }
+        protected void decrement_stats() {
+            synchronized (DefaultUnmapper.class) {
+                count--;
+                totalSize -= size;
+                totalCapacity -= cap;
+            }
+        }
+    }
+    
+    private static class PersistentUnmapper extends Unmapper {
+
+        // keep track of mapped buffer usage
+        static volatile int count;
+        static volatile long totalSize;
+        static volatile long totalCapacity;
+
+        public PersistentUnmapper(long address, long size, int cap,
+                                  FileDescriptor fd) {
+            super(address, size, cap, fd);
+            increment_stats();
+        }
+        
+        protected void increment_stats() {
+            synchronized (PersistentUnmapper.class) {
+                count++;
+                totalSize += size;
+                totalCapacity += cap;
+            }
+        }
+        protected void decrement_stats() {
+            synchronized (PersistentUnmapper.class) {
                 count--;
                 totalSize -= size;
                 totalCapacity -= cap;
             }
         }

@@ -945,16 +990,25 @@
             throw new IllegalArgumentException("Position + size overflow");
         if (size > Integer.MAX_VALUE)
             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
 
         int imode = -1;
+        boolean isPersistent = false;
         if (mode == MapMode.READ_ONLY)
             imode = MAP_RO;
         else if (mode == MapMode.READ_WRITE)
             imode = MAP_RW;
-        else if (mode == MapMode.PRIVATE)
+        else if (mode == MapMode.PRIVATE) {
             imode = MAP_PV;
+        } else if (mode == MapMode.READ_ONLY_PERSISTENT) {
+            imode = MAP_RO;
+            isPersistent = true;
+        } else if (mode == MapMode.READ_WRITE_PERSISTENT) {
+            imode = MAP_RW;
+            isPersistent = true;
+        }
+
         assert (imode >= 0);
         if ((mode != MapMode.READ_ONLY) && !writable)
             throw new NonWritableChannelException();
         if (!readable)
             throw new NonReadableChannelException();

@@ -993,32 +1047,32 @@
                 if (size == 0) {
                     addr = 0;
                     // a valid file descriptor is not required
                     FileDescriptor dummy = new FileDescriptor();
                     if ((!writable) || (imode == MAP_RO))
-                        return Util.newMappedByteBufferR(0, 0, dummy, null);
+                        return Util.newMappedByteBufferR(0, 0, dummy, null, isPersistent);
                     else
-                        return Util.newMappedByteBuffer(0, 0, dummy, null);
+                        return Util.newMappedByteBuffer(0, 0, dummy, null, isPersistent);
                 }
 
                 pagePosition = (int)(position % allocationGranularity);
                 long mapPosition = position - pagePosition;
                 mapSize = size + pagePosition;
                 try {
                     // If map0 did not throw an exception, the address is valid
-                    addr = map0(imode, mapPosition, mapSize);
+                    addr = map0(imode, mapPosition, mapSize, isPersistent);
                 } catch (OutOfMemoryError x) {
                     // An OutOfMemoryError may indicate that we've exhausted
                     // memory so force gc and re-attempt map
                     System.gc();
                     try {
                         Thread.sleep(100);
                     } catch (InterruptedException y) {
                         Thread.currentThread().interrupt();
                     }
                     try {
-                        addr = map0(imode, mapPosition, mapSize);
+                        addr = map0(imode, mapPosition, mapSize, isPersistent);
                     } catch (OutOfMemoryError y) {
                         // After a second OOME, fail
                         throw new IOException("Map failed", y);
                     }
                 }

@@ -1035,21 +1089,25 @@
             }
 
             assert (IOStatus.checkAll(addr));
             assert (addr % allocationGranularity == 0);
             int isize = (int)size;
-            Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+            Unmapper um = (isPersistent
+                           ? new PersistentUnmapper(addr, mapSize, isize, mfd)
+                           : new DefaultUnmapper(addr, mapSize, isize, mfd));
             if ((!writable) || (imode == MAP_RO)) {
                 return Util.newMappedByteBufferR(isize,
                                                  addr + pagePosition,
                                                  mfd,
-                                                 um);
+                                                 um,
+                                                 isPersistent);
             } else {
                 return Util.newMappedByteBuffer(isize,
                                                 addr + pagePosition,
                                                 mfd,
-                                                um);
+                                                um,
+                                                isPersistent);
             }
         } finally {
             threads.remove(ti);
             endBlocking(IOStatus.checkAll(addr));
         }

@@ -1065,19 +1123,44 @@
             public String getName() {
                 return "mapped";
             }
             @Override
             public long getCount() {
-                return Unmapper.count;
+                return DefaultUnmapper.count;
+            }
+            @Override
+            public long getTotalCapacity() {
+                return DefaultUnmapper.totalCapacity;
+            }
+            @Override
+            public long getMemoryUsed() {
+                return DefaultUnmapper.totalSize;
+            }
+        };
+    }
+
+    /**
+     * Invoked by sun.management.ManagementFactoryHelper to create the management
+     * interface for persistent mapped buffers.
+     */
+    public static JavaNioAccess.BufferPool getPersistentMappedBufferPool() {
+        return new JavaNioAccess.BufferPool() {
+            @Override
+            public String getName() {
+                return "mapped_persistent";
+            }
+            @Override
+            public long getCount() {
+                return PersistentUnmapper.count;
             }
             @Override
             public long getTotalCapacity() {
-                return Unmapper.totalCapacity;
+                return PersistentUnmapper.totalCapacity;
             }
             @Override
             public long getMemoryUsed() {
-                return Unmapper.totalSize;
+                return PersistentUnmapper.totalSize;
             }
         };
     }
 
     // -- Locks --

@@ -1199,11 +1282,11 @@
     }
 
     // -- Native methods --
 
     // Creates a new mapping
-    private native long map0(int prot, long position, long length)
+    private native long map0(int prot, long position, long length, boolean isPersistent)
         throws IOException;
 
     // Removes an existing mapping
     private static native int unmap0(long address, long length);
 
< prev index next >