/* * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// A user-settable upper limit on the maximum amount of allocatable // direct buffer memory. This value may be changed during VM // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". privatestaticvolatilelong MAX_MEMORY = VM.maxDirectMemory(); privatestaticfinal AtomicLong RESERVED_MEMORY = new AtomicLong(); privatestaticfinal AtomicLong TOTAL_CAPACITY = new AtomicLong(); privatestaticfinal AtomicLong COUNT = new AtomicLong(); privatestaticvolatileboolean MEMORY_LIMIT_SET;
// max. number of sleeps during try-reserving with exponentially // increasing delay before throwing OutOfMemoryError: // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) // which means that OOME will be thrown after 0.5 s of trying privatestaticfinalint MAX_SLEEPS = 9;
// These methods should be called whenever direct memory is allocated or // freed. They allow the user to control the amount of direct memory // which a process may access. All sizes are specified in bytes. staticvoid reserveMemory(long size, long cap) {
// Retry allocation until success or there are no more // references (including Cleaners that might free direct // buffer memory) to process and allocation still fails. boolean refprocActive; do { try {
refprocActive = jlra.waitForReferenceProcessing();
} catch (InterruptedException e) { // Defer interrupts and keep trying.
interrupted = true;
refprocActive = true;
} if (tryReserveMemory(size, cap)) { return;
}
} while (refprocActive);
// trigger VM's Reference processing
System.gc();
// A retry loop with exponential back-off delays. // Sometimes it would suffice to give up once reference // processing is complete. But if there are many threads // competing for memory, this gives more opportunities for // any given thread to make progress. In particular, this // seems to be enough for a stress test like // DirectBufferAllocTest to (usually) succeed, while // without it that test likely fails. Since failure here // ends in OOME, there's no need to hurry. long sleepTime = 1; int sleeps = 0; while (true) { if (tryReserveMemory(size, cap)) { return;
} if (sleeps >= MAX_SLEEPS) { break;
} try { if (!jlra.waitForReferenceProcessing()) { Thread.sleep(sleepTime);
sleepTime <<= 1;
sleeps++;
}
} catch (InterruptedException e) {
interrupted = true;
}
}
// no luck thrownew OutOfMemoryError
("Cannot reserve "
+ size + " bytes of direct buffer memory (allocated: "
+ RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")");
privatestaticboolean tryReserveMemory(long size, long cap) {
// -XX:MaxDirectMemorySize limits the total capacity rather than the // actual memory usage, which will differ when buffers are page // aligned. long totalCap; while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) { if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) {
RESERVED_MEMORY.addAndGet(size);
COUNT.incrementAndGet(); returntrue;
}
}
returnfalse;
}
staticvoid unreserveMemory(long size, long cap) { long cnt = COUNT.decrementAndGet(); long reservedMem = RESERVED_MEMORY.addAndGet(-size); long totalCap = TOTAL_CAPACITY.addAndGet(-cap); assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
}
// These numbers represent the point at which we have empirically // determined that the average cost of a JNI call exceeds the expense // of an element by element copy. These numbers may change over time. staticfinalint JNI_COPY_TO_ARRAY_THRESHOLD = 6; staticfinalint JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.