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.security.AccessController; 29 import sun.misc.Unsafe; 30 import sun.misc.VM; 31 32 /** 33 * Access to bits, native and otherwise. 34 */ 35 36 class Bits { // package-private 37 38 private Bits() { } 39 40 41 // -- Swapping -- 42 43 static short swap(short x) { 44 return Short.reverseBytes(x); 45 } 46 47 static char swap(char x) { 48 return Character.reverseBytes(x); 604 private static boolean unalignedKnown = false; 605 606 static boolean unaligned() { 607 if (unalignedKnown) 608 return unaligned; 609 String arch = AccessController.doPrivileged( 610 new sun.security.action.GetPropertyAction("os.arch")); 611 unaligned = arch.equals("i386") || arch.equals("x86") 612 || arch.equals("amd64") || arch.equals("x86_64"); 613 unalignedKnown = true; 614 return unaligned; 615 } 616 617 618 // -- Direct memory management -- 619 620 // A user-settable upper limit on the maximum amount of allocatable 621 // direct buffer memory. This value may be changed during VM 622 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 623 private static volatile long maxMemory = VM.maxDirectMemory(); 624 private static volatile long reservedMemory; 625 private static volatile long totalCapacity; 626 private static volatile long count; 627 private static boolean memoryLimitSet = false; 628 629 // These methods should be called whenever direct memory is allocated or 630 // freed. They allow the user to control the amount of direct memory 631 // which a process may access. All sizes are specified in bytes. 632 static void reserveMemory(long size, int cap) { 633 synchronized (Bits.class) { 634 if (!memoryLimitSet && VM.isBooted()) { 635 maxMemory = VM.maxDirectMemory(); 636 memoryLimitSet = true; 637 } 638 // -XX:MaxDirectMemorySize limits the total capacity rather than the 639 // actual memory usage, which will differ when buffers are page 640 // aligned. 641 if (cap <= maxMemory - totalCapacity) { 642 reservedMemory += size; 643 totalCapacity += cap; 644 count++; 645 return; 646 } 647 } 648 649 System.gc(); 650 try { 651 Thread.sleep(100); 652 } catch (InterruptedException x) { 653 // Restore interrupt status 654 Thread.currentThread().interrupt(); 655 } 656 synchronized (Bits.class) { 657 if (totalCapacity + cap > maxMemory) 658 throw new OutOfMemoryError("Direct buffer memory"); 659 reservedMemory += size; 660 totalCapacity += cap; 661 count++; 662 } 663 664 } 665 666 static synchronized void unreserveMemory(long size, int cap) { 667 if (reservedMemory > 0) { 668 reservedMemory -= size; 669 totalCapacity -= cap; 670 count--; 671 assert (reservedMemory > -1); 672 } 673 } 674 675 // -- Monitoring of direct buffer usage -- 676 677 static { 678 // setup access to this package in SharedSecrets 679 sun.misc.SharedSecrets.setJavaNioAccess( 680 new sun.misc.JavaNioAccess() { 681 @Override 682 public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { 683 return new sun.misc.JavaNioAccess.BufferPool() { 684 @Override 685 public String getName() { 686 return "direct"; 687 } 688 @Override 689 public long getCount() { 690 return Bits.count; 691 } 692 @Override 693 public long getTotalCapacity() { 694 return Bits.totalCapacity; 695 } 696 @Override 697 public long getMemoryUsed() { 698 return Bits.reservedMemory; 699 } 700 }; 701 } 702 @Override 703 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { 704 return new DirectByteBuffer(addr, cap, ob); 705 } 706 @Override 707 public void truncate(Buffer buf) { 708 buf.truncate(); 709 } 710 }); 711 } 712 713 // -- Bulk get/put acceleration -- 714 715 // These numbers represent the point at which we have empirically 716 // determined that the average cost of a JNI call exceeds the expense 717 // of an element by element copy. These numbers may change over time. 718 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; | 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.security.AccessController; 29 import java.util.concurrent.atomic.AtomicLong; 30 import java.util.concurrent.atomic.LongAdder; 31 32 import sun.misc.JavaLangRefAccess; 33 import sun.misc.SharedSecrets; 34 import sun.misc.Unsafe; 35 import sun.misc.VM; 36 37 /** 38 * Access to bits, native and otherwise. 39 */ 40 41 class Bits { // package-private 42 43 private Bits() { } 44 45 46 // -- Swapping -- 47 48 static short swap(short x) { 49 return Short.reverseBytes(x); 50 } 51 52 static char swap(char x) { 53 return Character.reverseBytes(x); 609 private static boolean unalignedKnown = false; 610 611 static boolean unaligned() { 612 if (unalignedKnown) 613 return unaligned; 614 String arch = AccessController.doPrivileged( 615 new sun.security.action.GetPropertyAction("os.arch")); 616 unaligned = arch.equals("i386") || arch.equals("x86") 617 || arch.equals("amd64") || arch.equals("x86_64"); 618 unalignedKnown = true; 619 return unaligned; 620 } 621 622 623 // -- Direct memory management -- 624 625 // A user-settable upper limit on the maximum amount of allocatable 626 // direct buffer memory. This value may be changed during VM 627 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 628 private static volatile long maxMemory = VM.maxDirectMemory(); 629 private static final AtomicLong reservedMemory = new AtomicLong(); 630 private static final AtomicLong totalCapacity = new AtomicLong(); 631 private static final AtomicLong count = new AtomicLong(); 632 private static volatile boolean memoryLimitSet = false; 633 // max. number of sleeps during try-reserving with exponentially 634 // increasing delay before throwing OutOfMemoryError: 635 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) 636 // which means that OOME will be thrown after 0.5 s of trying 637 private static final int MAX_SLEEPS = 9; 638 639 // These methods should be called whenever direct memory is allocated or 640 // freed. They allow the user to control the amount of direct memory 641 // which a process may access. All sizes are specified in bytes. 642 static void reserveMemory(long size, int cap) { 643 644 if (!memoryLimitSet && VM.isBooted()) { 645 maxMemory = VM.maxDirectMemory(); 646 memoryLimitSet = true; 647 } 648 649 // optimist! 650 if (tryReserveMemory(size, cap)) { 651 return; 652 } 653 654 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 655 656 // retry while helping enqueue pending Reference objects 657 // which includes executing pending Cleaner(s) which includes 658 // Cleaner(s) that free direct buffer memory 659 while (jlra.tryHandlePendingReference()) { 660 if (tryReserveMemory(size, cap)) { 661 return; 662 } 663 } 664 665 // trigger VM's Reference processing 666 System.gc(); 667 668 // a retry loop with exponential back-off delays 669 // (this gives VM some time to do it's job) 670 boolean interrupted = false; 671 try { 672 long sleepTime = 1; 673 int sleeps = 0; 674 while (true) { 675 if (tryReserveMemory(size, cap)) { 676 return; 677 } 678 if (sleeps >= MAX_SLEEPS) { 679 break; 680 } 681 if (!jlra.tryHandlePendingReference()) { 682 try { 683 Thread.sleep(sleepTime); 684 sleepTime <<= 1; 685 sleeps++; 686 } catch (InterruptedException e) { 687 interrupted = true; 688 } 689 } 690 } 691 692 // no luck 693 throw new OutOfMemoryError("Direct buffer memory"); 694 695 } finally { 696 if (interrupted) { 697 // don't swallow interrupts 698 Thread.currentThread().interrupt(); 699 } 700 } 701 } 702 703 private static boolean tryReserveMemory(long size, int cap) { 704 705 // -XX:MaxDirectMemorySize limits the total capacity rather than the 706 // actual memory usage, which will differ when buffers are page 707 // aligned. 708 long totalCap; 709 while (cap <= maxMemory - (totalCap = totalCapacity.get())) { 710 if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) { 711 reservedMemory.addAndGet(size); 712 count.incrementAndGet(); 713 return true; 714 } 715 } 716 717 return false; 718 } 719 720 721 static void unreserveMemory(long size, int cap) { 722 long cnt = count.decrementAndGet(); 723 long reservedMem = reservedMemory.addAndGet(-size); 724 long totalCap = totalCapacity.addAndGet(-cap); 725 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 726 } 727 728 // -- Monitoring of direct buffer usage -- 729 730 static { 731 // setup access to this package in SharedSecrets 732 sun.misc.SharedSecrets.setJavaNioAccess( 733 new sun.misc.JavaNioAccess() { 734 @Override 735 public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { 736 return new sun.misc.JavaNioAccess.BufferPool() { 737 @Override 738 public String getName() { 739 return "direct"; 740 } 741 @Override 742 public long getCount() { 743 return Bits.count.get(); 744 } 745 @Override 746 public long getTotalCapacity() { 747 return Bits.totalCapacity.get(); 748 } 749 @Override 750 public long getMemoryUsed() { 751 return Bits.reservedMemory.get(); 752 } 753 }; 754 } 755 @Override 756 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { 757 return new DirectByteBuffer(addr, cap, ob); 758 } 759 @Override 760 public void truncate(Buffer buf) { 761 buf.truncate(); 762 } 763 }); 764 } 765 766 // -- Bulk get/put acceleration -- 767 768 // These numbers represent the point at which we have empirically 769 // determined that the average cost of a JNI call exceeds the expense 770 // of an element by element copy. These numbers may change over time. 771 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; |