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