< prev index next >

src/java.base/share/classes/java/nio/Bits.java

Print this page




   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.nio;
  27 
  28 import java.util.concurrent.atomic.AtomicLong;

  29 
  30 import jdk.internal.misc.JavaNioAccess;
  31 import jdk.internal.misc.JavaLangRefAccess;
  32 import jdk.internal.misc.SharedSecrets;
  33 import jdk.internal.misc.Unsafe;
  34 import jdk.internal.misc.VM;
  35 
  36 /**
  37  * Access to bits, native and otherwise.
  38  */
  39 
  40 class Bits {                            // package-private
  41 
  42     private Bits() { }
  43 
  44 
  45     // -- Swapping --
  46 
  47     static short swap(short x) {
  48         return Short.reverseBytes(x);
  49     }
  50 
  51     static char swap(char x) {
  52         return Character.reverseBytes(x);
  53     }
  54 


 592     }
 593 
 594 
 595     // -- Direct memory management --
 596 
 597     // A user-settable upper limit on the maximum amount of allocatable
 598     // direct buffer memory.  This value may be changed during VM
 599     // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
 600     private static volatile long maxMemory = VM.maxDirectMemory();
 601     private static final AtomicLong reservedMemory = new AtomicLong();
 602     private static final AtomicLong totalCapacity = new AtomicLong();
 603     private static final AtomicLong count = new AtomicLong();
 604     private static volatile boolean memoryLimitSet;
 605 
 606     // max. number of sleeps during try-reserving with exponentially
 607     // increasing delay before throwing OutOfMemoryError:
 608     // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
 609     // which means that OOME will be thrown after 0.5 s of trying
 610     private static final int MAX_SLEEPS = 9;
 611 


 612     // These methods should be called whenever direct memory is allocated or
 613     // freed.  They allow the user to control the amount of direct memory
 614     // which a process may access.  All sizes are specified in bytes.
 615     static void reserveMemory(long size, int cap) {
 616 
 617         if (!memoryLimitSet && VM.isBooted()) {
 618             maxMemory = VM.maxDirectMemory();
 619             memoryLimitSet = true;
 620         }
 621 
 622         // optimist!
 623         if (tryReserveMemory(size, cap)) {
 624             return;
 625         }
 626 
 627         final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();




 628 
 629         // retry while helping enqueue pending Reference objects
 630         // which includes executing pending Cleaner(s) which includes
 631         // Cleaner(s) that free direct buffer memory
 632         while (jlra.tryHandlePendingReference()) {
 633             if (tryReserveMemory(size, cap)) {
 634                 return;
 635             }
 636         }
 637 
 638         // trigger VM's Reference processing
 639         System.gc();


 640 
 641         // a retry loop with exponential back-off delays
 642         // (this gives VM some time to do it's job)
 643         boolean interrupted = false;
 644         try {
 645             long sleepTime = 1;
 646             int sleeps = 0;
 647             while (true) {
 648                 if (tryReserveMemory(size, cap)) {
 649                     return;
 650                 }
 651                 if (sleeps >= MAX_SLEEPS) {
 652                     break;
 653                 }
 654                 if (!jlra.tryHandlePendingReference()) {
 655                     try {
 656                         Thread.sleep(sleepTime);
 657                         sleepTime <<= 1;
 658                         sleeps++;
 659                     } catch (InterruptedException e) {
 660                         interrupted = true;
 661                     }
 662                 }
 663             }
 664 
 665             // no luck
 666             throw new OutOfMemoryError("Direct buffer memory");
 667 
 668         } finally {
 669             if (interrupted) {
 670                 // don't swallow interrupts
 671                 Thread.currentThread().interrupt();
 672             }
 673         }
 674     }
 675 
 676     private static boolean tryReserveMemory(long size, int cap) {
 677 
 678         // -XX:MaxDirectMemorySize limits the total capacity rather than the
 679         // actual memory usage, which will differ when buffers are page
 680         // aligned.
 681         long totalCap;
 682         while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
 683             if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
 684                 reservedMemory.addAndGet(size);
 685                 count.incrementAndGet();
 686                 return true;
 687             }
 688         }
 689 
 690         return false;
 691     }
 692 




   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.nio;
  27 
  28 import java.util.concurrent.atomic.AtomicLong;
  29 import java.util.concurrent.locks.ReentrantLock;
  30 
  31 import jdk.internal.misc.*;
  32 import jdk.internal.ref.CleanerFactory;



  33 
  34 /**
  35  * Access to bits, native and otherwise.
  36  */
  37 
  38 class Bits {                            // package-private
  39 
  40     private Bits() { }
  41 
  42 
  43     // -- Swapping --
  44 
  45     static short swap(short x) {
  46         return Short.reverseBytes(x);
  47     }
  48 
  49     static char swap(char x) {
  50         return Character.reverseBytes(x);
  51     }
  52 


 590     }
 591 
 592 
 593     // -- Direct memory management --
 594 
 595     // A user-settable upper limit on the maximum amount of allocatable
 596     // direct buffer memory.  This value may be changed during VM
 597     // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
 598     private static volatile long maxMemory = VM.maxDirectMemory();
 599     private static final AtomicLong reservedMemory = new AtomicLong();
 600     private static final AtomicLong totalCapacity = new AtomicLong();
 601     private static final AtomicLong count = new AtomicLong();
 602     private static volatile boolean memoryLimitSet;
 603 
 604     // max. number of sleeps during try-reserving with exponentially
 605     // increasing delay before throwing OutOfMemoryError:
 606     // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
 607     // which means that OOME will be thrown after 0.5 s of trying
 608     private static final int MAX_SLEEPS = 9;
 609 
 610     private static final ReentrantLock reservationQueue = new ReentrantLock(true);
 611 
 612     // These methods should be called whenever direct memory is allocated or
 613     // freed.  They allow the user to control the amount of direct memory
 614     // which a process may access.  All sizes are specified in bytes.
 615     static void reserveMemory(long size, int cap) {
 616 
 617         if (!memoryLimitSet && VM.isBooted()) {
 618             maxMemory = VM.maxDirectMemory();
 619             memoryLimitSet = true;
 620         }
 621 
 622         // optimist!
 623         if (tryReserveMemory(size, cap)) {
 624             return;
 625         }
 626 
 627         // reservation threads that don't succeed at first must queue so that
 628         // some of them don't starve while others succeed.
 629         reservationQueue.lock();
 630         try {
 631             JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
 632 
 633             // retry reservation while helping the Cleaner thread process enqueued
 634             // Cleanable(s) which includes the ones that free direct buffer memory
 635             // until the queue drains out
 636             do {
 637                 if (tryReserveMemory(size, cap)) {
 638                     return;
 639                 }
 640             } while (jlra.cleanNextPendingCleanable(CleanerFactory.cleaner()));
 641 
 642             // trigger GC's Reference discovery
 643             System.gc();
 644             // make sure all newly discovered Reference(s) are enqueued
 645             jlra.enqueuePendingReferences();
 646 
 647             // retry reservation while helping the Cleaner thread process enqueued
 648             // Cleanable(s) which includes the ones that free direct buffer memory
 649             // until the queue drains out
 650             do {



 651                 if (tryReserveMemory(size, cap)) {
 652                     return;
 653                 }
 654             } while (jlra.cleanNextPendingCleanable(CleanerFactory.cleaner()));












 655 
 656             // no luck
 657             throw new OutOfMemoryError("Direct buffer memory");

 658         } finally {
 659             reservationQueue.unlock();



 660         }
 661     }
 662 
 663     private static boolean tryReserveMemory(long size, int cap) {
 664 
 665         // -XX:MaxDirectMemorySize limits the total capacity rather than the
 666         // actual memory usage, which will differ when buffers are page
 667         // aligned.
 668         long totalCap;
 669         while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
 670             if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
 671                 reservedMemory.addAndGet(size);
 672                 count.incrementAndGet();
 673                 return true;
 674             }
 675         }
 676 
 677         return false;
 678     }
 679 


< prev index next >