Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/nio/Bits.java
41152 views
1
/*
2
* Copyright (c) 2000, 2021, 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.access.JavaLangRefAccess;
29
import jdk.internal.access.SharedSecrets;
30
import jdk.internal.misc.Unsafe;
31
import jdk.internal.misc.VM;
32
import jdk.internal.misc.VM.BufferPool;
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 long pageCount(long size) {
79
return (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, long 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
176
("Cannot reserve "
177
+ size + " bytes of direct buffer memory (allocated: "
178
+ RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")");
179
180
} finally {
181
if (interrupted) {
182
// don't swallow interrupts
183
Thread.currentThread().interrupt();
184
}
185
}
186
}
187
188
private static boolean tryReserveMemory(long size, long cap) {
189
190
// -XX:MaxDirectMemorySize limits the total capacity rather than the
191
// actual memory usage, which will differ when buffers are page
192
// aligned.
193
long totalCap;
194
while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) {
195
if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) {
196
RESERVED_MEMORY.addAndGet(size);
197
COUNT.incrementAndGet();
198
return true;
199
}
200
}
201
202
return false;
203
}
204
205
206
static void unreserveMemory(long size, long cap) {
207
long cnt = COUNT.decrementAndGet();
208
long reservedMem = RESERVED_MEMORY.addAndGet(-size);
209
long totalCap = TOTAL_CAPACITY.addAndGet(-cap);
210
assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
211
}
212
213
static final BufferPool BUFFER_POOL = new BufferPool() {
214
@Override
215
public String getName() {
216
return "direct";
217
}
218
@Override
219
public long getCount() {
220
return Bits.COUNT.get();
221
}
222
@Override
223
public long getTotalCapacity() {
224
return Bits.TOTAL_CAPACITY.get();
225
}
226
@Override
227
public long getMemoryUsed() {
228
return Bits.RESERVED_MEMORY.get();
229
}
230
};
231
232
// These numbers represent the point at which we have empirically
233
// determined that the average cost of a JNI call exceeds the expense
234
// of an element by element copy. These numbers may change over time.
235
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
236
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
237
}
238
239