/*
* Copyright ( c ) 2014 , 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 .
*
* 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 .
*/
/**
* @ test
* @ bug 6857566
* @ summary DirectByteBuffer garbage creation can outpace reclamation
*
* @ run main / othervm - XX : MaxDirectMemorySize = 128 m - XX : - ExplicitGCInvokesConcurrent DirectBufferAllocTest
*/
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class DirectBufferAllocTest {
// defaults
static final int RUN_TIME_SECONDS = 5 ;
static final int MIN_THREADS = 4 ;
static final int MAX_THREADS = 64 ;
static final int CAPACITY = 1024 * 1024 ; // bytes
/**
* This test spawns multiple threads that constantly allocate direct
* { @ link ByteBuffer } s in a loop , trying to provoke { @ link OutOfMemoryError } . < p >
* When run without command - line arguments , it runs as a regression test
* for at most 5 seconds . < p >
* Command line arguments :
* < pre >
* - r run - time - seconds < i > ( duration of successful test - default 5 s ) < / i >
* - t threads < i > ( default is 2 * # of CPUs , at least 4 but no more than 64 ) < / i >
* - c capacity < i > ( of direct buffers in bytes - default is 1 MB ) < / i >
* - p print - alloc - time - batch - size < i > ( every " batch size " iterations ,
* average time per allocation is printed ) < / i >
* < / pre >
* Use something like the following to run a 10 minute stress test and
* print allocation times as it goes :
* < pre >
* java - XX : MaxDirectMemorySize = 128 m DirectBufferAllocTest - r 600 - t 32 - p 5000
* < / pre >
*/
public static void main(String[] args) throws Exception {
int runTimeSeconds = RUN_TIME_SECONDS;
int threads = Math.max(
Math.min(
Runtime.getRuntime().availableProcessors() * 2 ,
MAX_THREADS
),
MIN_THREADS
);
int capacity = CAPACITY;
int printBatchSize = 0 ;
// override with command line arguments
for (int i = 0 ; i < args.length; i++) {
switch (args[i]) {
case "-r" :
runTimeSeconds = Integer.parseInt(args[++i]);
break ;
case "-t" :
threads = Integer.parseInt(args[++i]);
break ;
case "-c" :
capacity = Integer.parseInt(args[++i]);
break ;
case "-p" :
printBatchSize = Integer.parseInt(args[++i]);
break ;
default :
System.err.println(
"Usage: java" +
" [-XX:MaxDirectMemorySize=XXXm]" +
" DirectBufferAllocTest" +
" [-r run-time-seconds]" +
" [-t threads]" +
" [-c capacity-of-direct-buffers]" +
" [-p print-alloc-time-batch-size]"
);
System.exit(-1 );
}
}
System.out.printf(
"Allocating direct ByteBuffers with capacity %d bytes, using %d threads for %d seconds...\n" ,
capacity, threads, runTimeSeconds
);
ExecutorService executor = Executors.newFixedThreadPool(threads);
int pbs = printBatchSize;
int cap = capacity;
List<Future<Void >> futures =
IntStream.range(0 , threads)
.mapToObj(
i -> (Callable<Void >) () -> {
long t0 = System.nanoTime();
loop:
while (true ) {
for (int n = 0 ; pbs == 0 || n < pbs; n++) {
if (Thread .interrupted()) {
break loop;
}
ByteBuffer.allocateDirect(cap);
}
long t1 = System.nanoTime();
if (pbs > 0 ) {
System.out.printf(
"Thread %2d: %5.2f ms/allocation\n" ,
i, ((double ) (t1 - t0) / (1 _000 _000 d * pbs))
);
}
t0 = t1;
}
return null ;
}
)
.map(executor::submit)
.collect(Collectors.toList());
for (int i = 0 ; i < runTimeSeconds; i++) {
if (futures.stream().anyMatch(Future::isDone)) {
break ;
}
Thread .sleep(1000 L);
}
Exception exception = null ;
for (Future<Void > future : futures) {
if (future.isDone()) {
try {
future.get();
} catch (ExecutionException e) {
if (exception == null ) {
exception = new RuntimeException("Errors encountered!" );
}
exception.addSuppressed(e.getCause());
}
} else {
future.cancel(true );
}
}
executor.shutdown();
if (exception != null ) {
throw exception;
} else {
System.out.printf("No errors after %d seconds.\n" , runTimeSeconds);
}
}
}
Messung V0.5 in Prozent C=94 H=90 G=91
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland