8 * particular file as subject to the "Classpath" exception as provided 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 580 pageSize = unsafe().pageSize(); 581 return pageSize; 582 } 583 584 static int pageCount(long size) { 585 return (int)(size + (long)pageSize() - 1L) / pageSize(); 586 } 587 588 private static boolean unaligned = unsafe.unalignedAccess(); 589 590 static boolean unaligned() { 591 return unaligned; 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.initLevel() >= 1) { 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 693 694 static void unreserveMemory(long size, int cap) { 695 long cnt = count.decrementAndGet(); 696 long reservedMem = reservedMemory.addAndGet(-size); 697 long totalCap = totalCapacity.addAndGet(-cap); 698 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 699 } 700 701 // -- Monitoring of direct buffer usage -- 702 703 static { 704 // setup access to this package in SharedSecrets 705 SharedSecrets.setJavaNioAccess( 706 new JavaNioAccess() { 707 @Override 708 public JavaNioAccess.BufferPool getDirectBufferPool() { 709 return new JavaNioAccess.BufferPool() { 710 @Override 711 public String getName() { 712 return "direct"; 713 } 714 @Override 715 public long getCount() { 716 return Bits.count.get(); 717 } 718 @Override | 8 * particular file as subject to the "Classpath" exception as provided 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.TimeUnit; 29 import java.util.concurrent.atomic.AtomicLong; 30 import java.util.concurrent.locks.StampedLock; 31 32 import jdk.internal.misc.JavaNioAccess; 33 import jdk.internal.misc.JavaLangRefAccess; 34 import jdk.internal.misc.SharedSecrets; 35 import jdk.internal.misc.Unsafe; 36 import jdk.internal.misc.VM; 37 import jdk.internal.ref.CleanerFactory; 38 39 /** 40 * Access to bits, native and otherwise. 41 */ 42 43 class Bits { // package-private 44 45 private Bits() { } 46 47 48 // -- Swapping -- 49 50 static short swap(short x) { 51 return Short.reverseBytes(x); 52 } 53 54 static char swap(char x) { 55 return Character.reverseBytes(x); 56 } 57 583 pageSize = unsafe().pageSize(); 584 return pageSize; 585 } 586 587 static int pageCount(long size) { 588 return (int)(size + (long)pageSize() - 1L) / pageSize(); 589 } 590 591 private static boolean unaligned = unsafe.unalignedAccess(); 592 593 static boolean unaligned() { 594 return unaligned; 595 } 596 597 598 // -- Direct memory management -- 599 600 // A user-settable upper limit on the maximum amount of allocatable 601 // direct buffer memory. This value may be changed during VM 602 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 603 // A change to maxMemory is published via memoryLimitSet volatile boolean 604 // flag changing state from false -> true, so maxMemory need not be volatile. 605 private static long maxMemory = VM.maxDirectMemory(); 606 private static volatile boolean memoryLimitSet; 607 608 private static final AtomicLong reservedMemory = new AtomicLong(); 609 private static final AtomicLong totalCapacity = new AtomicLong(); 610 private static final AtomicLong count = new AtomicLong(); 611 612 // A fair lock for direct memory allocator threads to queue after 1st optimistic 613 // reservation fails so that only a single thread at a time is retrying 614 // reservation while: 615 // - waiting for unreservation events until time out 616 // - followed by triggering reference discovery 617 // - followed by another round of waiting for unreservation events until time out 618 // ... before finally giving up with OutOfMemoryError. 619 private static final StampedLock reserveLock = new StampedLock(); 620 621 // A counter of unreservations incremented by unreservation threads, 622 // guarded by unreserveLock, but also read by reservation threads without 623 // holding unreserveLock, so it must be volatile. 624 private static volatile int unreserveCount; 625 626 // Last value of 'unreserveCount' observed by reservation threads, 627 // guarded by reserveLock. If 'lastUnreserveCount' and 'unreserveCount' 628 // differ, an unreservation event (or multiple events) is detected. 629 private static int lastUnreserveCount; 630 631 // the System.nanoTime() of the detection of last unreservation event 632 // by the reservation thread(s), guarded by reserveLock. 633 private static long lastUnreserveNanoTime; 634 635 // flag indicating if 'lastUnreserveNanoTime' has already been set, 636 // guarded by reserveLock. 637 private static boolean lastUnreserveNanoTimeSet; 638 639 // max. wait time for unreservation event before triggering GC and/or 640 // failing with OOME. 641 private static final long MAX_UNRESERVE_WAIT_NANOS = 642 TimeUnit.SECONDS.toNanos(1L); 643 644 // the duration of last successful waiting for unreservation 645 // event by reservation thread. starts with MAX_UNRESERVE_WAIT_NANOS / 4 646 // and is dynamically adjusted at each successful call to awaitUnreserveMemory() 647 // that actually waited for the event. 648 private static long lastSuccessfullUnreserveWaitNanos = 649 MAX_UNRESERVE_WAIT_NANOS / 4; 650 651 // monitor lock via which unreservation threads notify reservation threads 652 // about the unreservation events. 653 private static final Object unreserveLock = new Object(); 654 655 // These methods should be called whenever direct memory is allocated or 656 // freed. They allow the user to control the amount of direct memory 657 // which a process may access. All sizes are specified in bytes. 658 static void reserveMemory(long size, int cap) { 659 660 if (!memoryLimitSet && VM.initLevel() >= 1) { 661 maxMemory = VM.maxDirectMemory(); 662 memoryLimitSet = true; 663 } 664 665 JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 666 667 // optimist! 668 long stamp = reserveLock.tryReadLock(); 669 if (stamp != 0L) try { 670 // retry reservation while helping the Cleaner thread process enqueued 671 // Cleanable(s) which includes the ones that free direct buffer memory 672 // until the queue drains out 673 do { 674 if (tryReserveMemory(size, cap)) { 675 return; 676 } 677 } while (jlra.cleanNextEnqueuedCleanable(CleanerFactory.cleaner())); 678 } finally { 679 reserveLock.unlockRead(stamp); 680 } 681 682 // reservation threads that don't succeed at first must queue so that 683 // only one of them at a time is triggering reference discovery and 684 // retrials with waiting on un-reservation events... 685 stamp = reserveLock.writeLock(); 686 try { 687 // retry reservation until there are no unreservation events 688 // detected for at least 4 times as much as we waited for last 689 // successful unreservation event but no more than 690 // MAX_UNRESERVE_WAIT_NANOS. 691 do { 692 if (tryReserveMemory(size, cap)) { 693 return; 694 } 695 } while (awaitUnreserveMemory(Math.min(MAX_UNRESERVE_WAIT_NANOS, 696 lastSuccessfullUnreserveWaitNanos * 4))); 697 698 // trigger reference discovery 699 System.gc(); 700 // GC stops the world and can last for a long time, 701 // so restart timing from 0. 702 lastUnreserveNanoTime = System.nanoTime(); 703 704 // retry reservation until there are no unreservation events 705 // detected for at least MAX_UNRESERVE_WAIT_NANOS. 706 do { 707 if (tryReserveMemory(size, cap)) { 708 return; 709 } 710 } while (awaitUnreserveMemory(MAX_UNRESERVE_WAIT_NANOS)); 711 712 // no luck 713 throw new OutOfMemoryError("Direct buffer memory"); 714 } finally { 715 reserveLock.unlockWrite(stamp); 716 } 717 } 718 719 private static boolean tryReserveMemory(long size, int cap) { 720 721 // -XX:MaxDirectMemorySize limits the total capacity rather than the 722 // actual memory usage, which will differ when buffers are page 723 // aligned. 724 long totalCap; 725 while (cap <= maxMemory - (totalCap = totalCapacity.get())) { 726 if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) { 727 reservedMemory.addAndGet(size); 728 count.incrementAndGet(); 729 return true; 730 } 731 } 732 733 return false; 734 } 735 736 private static boolean awaitUnreserveMemory(long timeoutNanos) { 737 assert reserveLock.isWriteLocked(); 738 739 // optimistic 1st try without lock 740 int c; 741 if ((c = unreserveCount) != lastUnreserveCount) { 742 lastUnreserveCount = c; 743 lastUnreserveNanoTime = System.nanoTime(); 744 lastUnreserveNanoTimeSet = true; 745 return true; 746 } 747 boolean interrupted = false; 748 try { 749 synchronized (unreserveLock) { 750 long nt = System.nanoTime(); 751 if (!lastUnreserveNanoTimeSet) { 752 lastUnreserveNanoTime = nt; 753 lastUnreserveNanoTimeSet = true; 754 } 755 long deadline = lastUnreserveNanoTime + timeoutNanos; 756 long waitUnreserve; 757 while ((c = unreserveCount) == lastUnreserveCount && 758 (waitUnreserve = deadline - nt) > 0L) { 759 interrupted |= waitNanos(unreserveLock, waitUnreserve); 760 nt = System.nanoTime(); 761 } 762 if (c == lastUnreserveCount) { 763 // time out 764 return false; 765 } else { 766 lastSuccessfullUnreserveWaitNanos = nt - lastUnreserveNanoTime; 767 lastUnreserveCount = c; 768 lastUnreserveNanoTime = nt; 769 return true; 770 } 771 } 772 } finally { 773 if (interrupted) { 774 Thread.currentThread().interrupt(); 775 } 776 } 777 } 778 779 private static boolean waitNanos(Object lock, long waitNanos) { 780 try { 781 long millis = TimeUnit.NANOSECONDS.toMillis(waitNanos); 782 int nanos = (int) (waitNanos - TimeUnit.MILLISECONDS.toNanos(millis)); 783 lock.wait(millis, nanos); 784 return false; 785 } catch (InterruptedException e) { 786 return true; 787 } 788 } 789 790 static void unreserveMemory(long size, int cap) { 791 synchronized (unreserveLock) { 792 long cnt = count.decrementAndGet(); 793 long reservedMem = reservedMemory.addAndGet(-size); 794 long totalCap = totalCapacity.addAndGet(-cap); 795 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 796 unreserveCount++; 797 unreserveLock.notifyAll(); 798 } 799 } 800 801 // -- Monitoring of direct buffer usage -- 802 803 static { 804 // setup access to this package in SharedSecrets 805 SharedSecrets.setJavaNioAccess( 806 new JavaNioAccess() { 807 @Override 808 public JavaNioAccess.BufferPool getDirectBufferPool() { 809 return new JavaNioAccess.BufferPool() { 810 @Override 811 public String getName() { 812 return "direct"; 813 } 814 @Override 815 public long getCount() { 816 return Bits.count.get(); 817 } 818 @Override |