Path: blob/master/test/jdk/java/nio/Buffer/DirectBufferAllocTest.java
41149 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 685756626* @summary DirectByteBuffer garbage creation can outpace reclamation27*28* @run main/othervm -XX:MaxDirectMemorySize=128m -XX:-ExplicitGCInvokesConcurrent DirectBufferAllocTest29*/3031import java.nio.ByteBuffer;32import java.util.List;33import java.util.concurrent.*;34import java.util.stream.Collectors;35import java.util.stream.IntStream;3637public class DirectBufferAllocTest {38// defaults39static final int RUN_TIME_SECONDS = 5;40static final int MIN_THREADS = 4;41static final int MAX_THREADS = 64;42static final int CAPACITY = 1024 * 1024; // bytes4344/**45* This test spawns multiple threads that constantly allocate direct46* {@link ByteBuffer}s in a loop, trying to provoke {@link OutOfMemoryError}.<p>47* When run without command-line arguments, it runs as a regression test48* for at most 5 seconds.<p>49* Command line arguments:50* <pre>51* -r run-time-seconds <i>(duration of successful test - default 5 s)</i>52* -t threads <i>(default is 2 * # of CPUs, at least 4 but no more than 64)</i>53* -c capacity <i>(of direct buffers in bytes - default is 1MB)</i>54* -p print-alloc-time-batch-size <i>(every "batch size" iterations,55* average time per allocation is printed)</i>56* </pre>57* Use something like the following to run a 10 minute stress test and58* print allocation times as it goes:59* <pre>60* java -XX:MaxDirectMemorySize=128m DirectBufferAllocTest -r 600 -t 32 -p 500061* </pre>62*/63public static void main(String[] args) throws Exception {64int runTimeSeconds = RUN_TIME_SECONDS;65int threads = Math.max(66Math.min(67Runtime.getRuntime().availableProcessors() * 2,68MAX_THREADS69),70MIN_THREADS71);72int capacity = CAPACITY;73int printBatchSize = 0;7475// override with command line arguments76for (int i = 0; i < args.length; i++) {77switch (args[i]) {78case "-r":79runTimeSeconds = Integer.parseInt(args[++i]);80break;81case "-t":82threads = Integer.parseInt(args[++i]);83break;84case "-c":85capacity = Integer.parseInt(args[++i]);86break;87case "-p":88printBatchSize = Integer.parseInt(args[++i]);89break;90default:91System.err.println(92"Usage: java" +93" [-XX:MaxDirectMemorySize=XXXm]" +94" DirectBufferAllocTest" +95" [-r run-time-seconds]" +96" [-t threads]" +97" [-c capacity-of-direct-buffers]" +98" [-p print-alloc-time-batch-size]"99);100System.exit(-1);101}102}103104System.out.printf(105"Allocating direct ByteBuffers with capacity %d bytes, using %d threads for %d seconds...\n",106capacity, threads, runTimeSeconds107);108109ExecutorService executor = Executors.newFixedThreadPool(threads);110111int pbs = printBatchSize;112int cap = capacity;113114List<Future<Void>> futures =115IntStream.range(0, threads)116.mapToObj(117i -> (Callable<Void>) () -> {118long t0 = System.nanoTime();119loop:120while (true) {121for (int n = 0; pbs == 0 || n < pbs; n++) {122if (Thread.interrupted()) {123break loop;124}125ByteBuffer.allocateDirect(cap);126}127long t1 = System.nanoTime();128if (pbs > 0) {129System.out.printf(130"Thread %2d: %5.2f ms/allocation\n",131i, ((double) (t1 - t0) / (1_000_000d * pbs))132);133}134t0 = t1;135}136return null;137}138)139.map(executor::submit)140.collect(Collectors.toList());141142for (int i = 0; i < runTimeSeconds; i++) {143if (futures.stream().anyMatch(Future::isDone)) {144break;145}146Thread.sleep(1000L);147}148149Exception exception = null;150for (Future<Void> future : futures) {151if (future.isDone()) {152try {153future.get();154} catch (ExecutionException e) {155if (exception == null) {156exception = new RuntimeException("Errors encountered!");157}158exception.addSuppressed(e.getCause());159}160} else {161future.cancel(true);162}163}164165executor.shutdown();166167if (exception != null) {168throw exception;169} else {170System.out.printf("No errors after %d seconds.\n", runTimeSeconds);171}172}173}174175176