1 /*
2 * Copyright (c) 2000, 2016, Oracle and/or its affiliates. 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. Oracle designates this
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 jdk.internal.misc.JavaLangRefAccess;
29 import jdk.internal.misc.JavaNioAccess;
30 import jdk.internal.misc.SharedSecrets;
31 import jdk.internal.misc.Unsafe;
32 import jdk.internal.misc.VM;
33
34 import java.util.concurrent.atomic.AtomicLong;
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
55 static int swap(int x) {
56 return Integer.reverseBytes(x);
57 }
58
59 static long swap(long x) {
60 return Long.reverseBytes(x);
61 }
62
63
64 // -- Unsafe access --
65
66 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
67
68 // -- Processor and memory-system properties --
69
70 private static int PAGE_SIZE = -1;
71
72 static int pageSize() {
73 if (PAGE_SIZE == -1)
74 PAGE_SIZE = UNSAFE.pageSize();
75 return PAGE_SIZE;
76 }
77
78 static int pageCount(long size) {
79 return (int)(size + (long)pageSize() - 1L) / pageSize();
80 }
81
82 private static boolean UNALIGNED = UNSAFE.unalignedAccess();
83
84 static boolean unaligned() {
85 return UNALIGNED;
86 }
87
88
89 // -- Direct memory management --
90
91 // A user-settable upper limit on the maximum amount of allocatable
92 // direct buffer memory. This value may be changed during VM
93 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
94 private static volatile long MAX_MEMORY = VM.maxDirectMemory();
95 private static final AtomicLong RESERVED_MEMORY = new AtomicLong();
96 private static final AtomicLong TOTAL_CAPACITY = new AtomicLong();
97 private static final AtomicLong COUNT = new AtomicLong();
98 private static volatile boolean MEMORY_LIMIT_SET;
99
100 // max. number of sleeps during try-reserving with exponentially
101 // increasing delay before throwing OutOfMemoryError:
102 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
103 // which means that OOME will be thrown after 0.5 s of trying
104 private static final int MAX_SLEEPS = 9;
105
106 // These methods should be called whenever direct memory is allocated or
107 // freed. They allow the user to control the amount of direct memory
108 // which a process may access. All sizes are specified in bytes.
109 static void reserveMemory(long size, int cap) {
110
111 if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) {
112 MAX_MEMORY = VM.maxDirectMemory();
113 MEMORY_LIMIT_SET = true;
114 }
115
116 // optimist!
117 if (tryReserveMemory(size, cap)) {
118 return;
119 }
120
121 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
122 boolean interrupted = false;
123 try {
124
125 // Retry allocation until success or there are no more
126 // references (including Cleaners that might free direct
127 // buffer memory) to process and allocation still fails.
128 boolean refprocActive;
129 do {
130 try {
131 refprocActive = jlra.waitForReferenceProcessing();
132 } catch (InterruptedException e) {
133 // Defer interrupts and keep trying.
134 interrupted = true;
135 refprocActive = true;
136 }
137 if (tryReserveMemory(size, cap)) {
138 return;
139 }
140 } while (refprocActive);
141
142 // trigger VM's Reference processing
143 System.gc();
144
145 // A retry loop with exponential back-off delays.
146 // Sometimes it would suffice to give up once reference
147 // processing is complete. But if there are many threads
148 // competing for memory, this gives more opportunities for
149 // any given thread to make progress. In particular, this
150 // seems to be enough for a stress test like
151 // DirectBufferAllocTest to (usually) succeed, while
152 // without it that test likely fails. Since failure here
153 // ends in OOME, there's no need to hurry.
154 long sleepTime = 1;
155 int sleeps = 0;
156 while (true) {
157 if (tryReserveMemory(size, cap)) {
158 return;
159 }
160 if (sleeps >= MAX_SLEEPS) {
161 break;
162 }
163 try {
164 if (!jlra.waitForReferenceProcessing()) {
165 Thread.sleep(sleepTime);
166 sleepTime <<= 1;
167 sleeps++;
168 }
169 } catch (InterruptedException e) {
170 interrupted = true;
171 }
172 }
173
174 // no luck
175 throw new OutOfMemoryError("Direct buffer memory");
176
177 } finally {
178 if (interrupted) {
179 // don't swallow interrupts
180 Thread.currentThread().interrupt();
181 }
182 }
183 }
184
185 private static boolean tryReserveMemory(long size, int cap) {
186
187 // -XX:MaxDirectMemorySize limits the total capacity rather than the
188 // actual memory usage, which will differ when buffers are page
189 // aligned.
190 long totalCap;
191 while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) {
192 if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) {
193 RESERVED_MEMORY.addAndGet(size);
194 COUNT.incrementAndGet();
195 return true;
196 }
197 }
198
199 return false;
200 }
201
202
203 static void unreserveMemory(long size, int cap) {
204 long cnt = COUNT.decrementAndGet();
205 long reservedMem = RESERVED_MEMORY.addAndGet(-size);
206 long totalCap = TOTAL_CAPACITY.addAndGet(-cap);
207 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
208 }
209
210 static final JavaNioAccess.BufferPool BUFFER_POOL = new JavaNioAccess.BufferPool() {
211 @Override
212 public String getName() {
213 return "direct";
214 }
215 @Override
216 public long getCount() {
217 return Bits.COUNT.get();
218 }
219 @Override
220 public long getTotalCapacity() {
221 return Bits.TOTAL_CAPACITY.get();
222 }
223 @Override
224 public long getMemoryUsed() {
225 return Bits.RESERVED_MEMORY.get();
226 }
227 };
228
229 // These numbers represent the point at which we have empirically
230 // determined that the average cost of a JNI call exceeds the expense
231 // of an element by element copy. These numbers may change over time.
232 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
233 static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
234 }
235