undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2001, 2025, 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 4490253 6535542 8357959
* @key randomness
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @summary Verify that newly allocated direct buffers are initialized.
* @run main/othervm AllocateDirectInit
*/
import java.nio.ByteBuffer;
import java.util.Random;
import jdk.test.lib.RandomFactory;
public class AllocateDirectInit {
private static final int MAX_BIN_LIMIT = 16 * 1024 * 1024;
private static final int MAX_DEC_LIMIT = 10 * 1000 * 1000;
private static final int TRIES_PER_LIMIT = 1024;
private static final Random RND = RandomFactory.getRandom();
public static void main(String [] args){
// Try power of two limits
for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) {
check(ByteBuffer.allocateDirect(limit - 1));
check(ByteBuffer.allocateDirect(limit));
check(ByteBuffer.allocateDirect(limit + 1));
}
// Try power of ten limits
for (int limit = 1; limit < MAX_DEC_LIMIT; limit *= 10) {
check(ByteBuffer.allocateDirect(limit - 1));
check(ByteBuffer.allocateDirect(limit));
check(ByteBuffer.allocateDirect(limit + 1));
}
// Try random sizes within power of two limits
for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) {
for (int t = 0; t < TRIES_PER_LIMIT; t++) {
check(ByteBuffer.allocateDirect(RND.nextInt(limit)));
}
}
}
private static void check(ByteBuffer bb) {
while (bb.hasRemaining()) {
if (bb.get() != 0) {
int mismatchPos = bb.position();
System.out.print("byte [");
for (bb.position(0); bb.position() < bb.limit(); ) {
System.out.print(" " + Integer.toHexString(bb.get() & 0xff));
}
System.out.println(" ]");
throw new RuntimeException("uninitialized buffer, position = " + mismatchPos);
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,144 @@
/*
* Copyright (c) 2000, 2023, 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
* @summary Unit test for buffers
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 5029431
* 5071718 6231529 6221101 6234263 6535542 6591971 6593946 6795561 7190219
* 7199551 8065556 8149469 8230665 8237514 8306374 8306623 8306959
* @modules java.base/java.nio:open
* java.base/jdk.internal.misc
* @author Mark Reinhold
*/
import java.io.PrintStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
public class Basic {
static PrintStream out = System.err;
static long ic(int i) {
int j = i % 54;
return j + 'a' + ((j > 26) ? 128 : 0);
}
static String toString(Buffer b) {
return (b.getClass().getName()
+ "[pos=" + b.position()
+ " lim=" + b.limit()
+ " cap=" + b.capacity()
+ "]");
}
static void show(int level, Buffer b) {
for (int i = 0; i < level; i++)
out.print(" ");
out.println(toString(b) + " " + Integer.toHexString(b.hashCode()));
}
static void fail(String s) {
throw new RuntimeException(s);
}
static void fail(String s, Buffer b) {
throw new RuntimeException(s + ": " + toString(b));
}
static void fail(String s, Buffer b, Buffer b2) {
throw new RuntimeException(s + ": "
+ toString(b) + ", " + toString(b2));
}
static void fail(Buffer b,
String expected, char expectedChar,
String got, char gotChar)
{
if (b instanceof ByteBuffer) {
ByteBuffer bb = (ByteBuffer)b;
int n = Math.min(16, bb.limit());
for (int i = 0; i < n; i++)
out.print(" " + Integer.toHexString(bb.get(i) & 0xff));
out.println();
}
if (b instanceof CharBuffer) {
CharBuffer bb = (CharBuffer)b;
int n = Math.min(16, bb.limit());
for (int i = 0; i < n; i++)
out.print(" " + Integer.toHexString(bb.get(i) & 0xffff));
out.println();
}
throw new RuntimeException(toString(b)
+ ": Expected '" + expectedChar + "'=0x"
+ expected
+ ", got '" + gotChar + "'=0x"
+ got);
}
static void fail(Buffer b, long expected, long got) {
fail(b,
Long.toHexString(expected), (char)expected,
Long.toHexString(got), (char)got);
}
static void ck(Buffer b, boolean cond) {
if (!cond)
fail("Condition failed", b);
}
static void ck(Buffer b, long got, long expected) {
if (expected != got)
fail(b, expected, got);
}
static void ck(Buffer b, float got, float expected) {
if (expected != got)
fail(b,
Float.toString(expected), (char)expected,
Float.toString(got), (char)got);
}
static void ck(Buffer b, double got, double expected) {
if (expected != got)
fail(b,
Double.toString(expected), (char)expected,
Double.toString(got), (char)got);
}
public static void main(String[] args) {
BasicByte.test();
BasicChar.test();
BasicShort.test();
BasicInt.test();
BasicLong.test();
BasicFloat.test();
BasicDouble.test();
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,425 @@
/*
* Copyright (c) 2020, 2026, 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.
*/
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ReadOnlyBufferException;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Stream;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*
* @test
* @bug 8219014 8245121
* @summary Ensure that a bulk put of a buffer into another is correct.
* @compile BulkPutBuffer.java
* @run junit/othervm BulkPutBuffer
*/
public class BulkPutBuffer {
static final long SEED = System.nanoTime();
static final MyRandom RND = new MyRandom(SEED);
static final int ITERATIONS = 100;
static final int MAX_CAPACITY = 1024;
static class MyRandom extends Random {
MyRandom(long seed) {
super(seed);
}
public byte nextByte() {
return (byte)next(8);
}
public char nextChar() {
return (char)next(16);
}
public short nextShort() {
return (short)next(16);
}
}
enum BufferKind {
HEAP,
HEAP_VIEW,
DIRECT,
STRING;
}
static final Map<Class<?>,TypeAttr> typeToAttr;
static record TypeAttr(Class<?> type, int bytes, String name) {}
static {
typeToAttr = Map.of(
byte.class, new TypeAttr(ByteBuffer.class, Byte.BYTES, "Byte"),
char.class, new TypeAttr(CharBuffer.class, Character.BYTES, "Char"),
short.class, new TypeAttr(ShortBuffer.class, Short.BYTES, "Short"),
int.class, new TypeAttr(IntBuffer.class, Integer.BYTES, "Int"),
float.class, new TypeAttr(FloatBuffer.class, Float.BYTES, "Float"),
long.class, new TypeAttr(LongBuffer.class, Long.BYTES, "Long"),
double.class, new TypeAttr(DoubleBuffer.class, Double.BYTES, "Double")
);
}
static BufferKind[] getKinds(Class<?> elementType) {
BufferKind[] kinds;
if (elementType == byte.class)
kinds = new BufferKind[] {
BufferKind.DIRECT,
BufferKind.HEAP
};
else if (elementType == char.class)
kinds = BufferKind.values();
else
kinds = new BufferKind[] {
BufferKind.DIRECT,
BufferKind.HEAP,
BufferKind.HEAP_VIEW
};
return kinds;
}
static ByteOrder[] getOrders(BufferKind kind, Class<?> elementType) {
switch (kind) {
case HEAP:
return new ByteOrder[] { ByteOrder.nativeOrder() };
default:
if (elementType == byte.class)
return new ByteOrder[] { ByteOrder.nativeOrder() };
else
return new ByteOrder[] { ByteOrder.BIG_ENDIAN,
ByteOrder.LITTLE_ENDIAN };
}
}
public static class BufferProxy {
final Class<?> elementType;
final BufferKind kind;
final ByteOrder order;
// Buffer methods
MethodHandle alloc;
MethodHandle allocBB;
MethodHandle allocDirect;
MethodHandle asReadOnlyBuffer;
MethodHandle asTypeBuffer;
MethodHandle putAbs;
MethodHandle getAbs;
MethodHandle putBufAbs;
MethodHandle putBufRel;
MethodHandle equals;
// MyRandom method
MethodHandle nextType;
BufferProxy(Class<?> elementType, BufferKind kind, ByteOrder order) {
this.elementType = elementType;
this.kind = kind;
this.order = order;
Class<?> bufferType = typeToAttr.get(elementType).type;
var lookup = MethodHandles.lookup();
try {
String name = typeToAttr.get(elementType).name;
alloc = lookup.findStatic(bufferType, "allocate",
MethodType.methodType(bufferType, int.class));
allocBB = lookup.findStatic(ByteBuffer.class, "allocate",
MethodType.methodType(ByteBuffer.class, int.class));
allocDirect = lookup.findStatic(ByteBuffer.class, "allocateDirect",
MethodType.methodType(ByteBuffer.class, int.class));
asReadOnlyBuffer = lookup.findVirtual(bufferType,
"asReadOnlyBuffer", MethodType.methodType(bufferType));
if (elementType != byte.class) {
asTypeBuffer = lookup.findVirtual(ByteBuffer.class,
"as" + name + "Buffer", MethodType.methodType(bufferType));
}
putAbs = lookup.findVirtual(bufferType, "put",
MethodType.methodType(bufferType, int.class, elementType));
getAbs = lookup.findVirtual(bufferType, "get",
MethodType.methodType(elementType, int.class));
putBufAbs = lookup.findVirtual(bufferType, "put",
MethodType.methodType(bufferType, int.class, bufferType,
int.class, int.class));
putBufRel = lookup.findVirtual(bufferType, "put",
MethodType.methodType(bufferType, bufferType));
equals = lookup.findVirtual(bufferType, "equals",
MethodType.methodType(boolean.class, Object.class));
nextType = lookup.findVirtual(MyRandom.class,
"next" + name, MethodType.methodType(elementType));
} catch (IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
Buffer create(int capacity) throws Throwable {
Class<?> bufferType = typeToAttr.get(elementType).type;
if (bufferType == ByteBuffer.class || kind == BufferKind.DIRECT ||
kind == BufferKind.HEAP_VIEW) {
int len = capacity*typeToAttr.get(elementType).bytes;
ByteBuffer bb = (ByteBuffer)allocBB.invoke(len);
byte[] bytes = new byte[len];
RND.nextBytes(bytes);
bb.put(0, bytes);
if (bufferType == ByteBuffer.class) {
return (Buffer)bb;
} else {
bb.order(order);
return (Buffer)asTypeBuffer.invoke(bb);
}
} else if (bufferType == CharBuffer.class &&
kind == BufferKind.STRING) {
char[] array = new char[capacity];
for (int i = 0; i < capacity; i++) {
array[i] = RND.nextChar();
}
return CharBuffer.wrap(new String(array));
} else {
Buffer buf = (Buffer)alloc.invoke(capacity);
for (int i = 0; i < capacity; i++) {
putAbs.invoke(buf, i, nextType.invoke(RND));
}
return buf;
}
}
void copy(Buffer src, int srcOff, Buffer dst, int dstOff, int length)
throws Throwable {
for (int i = 0; i < length; i++) {
putAbs.invoke(dst, dstOff + i, getAbs.invoke(src, srcOff + i));
}
}
Buffer asReadOnlyBuffer(Buffer buf) throws Throwable {
return (Buffer)asReadOnlyBuffer.invoke(buf);
}
void put(Buffer src, int srcOff, Buffer dst, int dstOff, int length)
throws Throwable {
putBufAbs.invoke(dst, dstOff, src, srcOff, length);
}
void put(Buffer src, Buffer dst) throws Throwable {
putBufRel.invoke(dst, src);
}
boolean equals(Buffer src, Buffer dst) throws Throwable {
return Boolean.class.cast(equals.invoke(dst, src));
}
}
static List<BufferProxy> getProxies(Class<?> type) {
List proxies = new ArrayList();
for (BufferKind kind : getKinds(type)) {
for (ByteOrder order : getOrders(kind, type)) {
proxies.add(new BufferProxy(type, kind, order));
}
}
return proxies;
}
static Stream<BufferProxy> proxies() {
List<BufferProxy> args = new ArrayList<BufferProxy>();
for (Class<?> type : typeToAttr.keySet()) {
List<BufferProxy> proxies = getProxies(type);
for (BufferProxy proxy : proxies) {
args.add(proxy);
}
}
return args.stream();
}
static Stream<Arguments> proxyPairs() {
List<Arguments> args = new ArrayList<Arguments>();
for (Class<?> type : typeToAttr.keySet()) {
List<BufferProxy> proxies = getProxies(type);
for (BufferProxy proxy1 : proxies) {
for (BufferProxy proxy2 : proxies) {
args.add(Arguments.of(proxy1, proxy2));
}
}
}
return args.stream();
}
@ParameterizedTest
@MethodSource("proxies")
public void testExceptions(BufferProxy bp) throws Throwable {
int cap = 27;
Buffer buf = bp.create(cap);
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, -1, buf, 0, 1));
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, 0, buf, -1, 1));
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, 1, buf, 0, cap));
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, 0, buf, 1, cap));
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, 0, buf, 0, cap + 1));
assertThrows(IndexOutOfBoundsException.class,
() -> bp.put(buf, 0, buf, 0, Integer.MAX_VALUE));
Buffer rob = buf.isReadOnly() ? buf : bp.asReadOnlyBuffer(buf);
assertThrows(ReadOnlyBufferException.class,
() -> bp.put(buf, 0, rob, 0, cap));
}
@ParameterizedTest
@MethodSource("proxies")
public void testSelf(BufferProxy bp) throws Throwable {
for (int i = 0; i < ITERATIONS; i++) {
int cap = RND.nextInt(MAX_CAPACITY);
Buffer buf = bp.create(cap);
int lowerOffset = RND.nextInt(1 + cap/10);
int lowerLength = RND.nextInt(1 + cap/2);
if (lowerLength < 2)
continue;
Buffer lower = buf.slice(lowerOffset, lowerLength);
Buffer lowerCopy = bp.create(lowerLength);
if (lowerCopy.isReadOnly()) {
assertThrows(ReadOnlyBufferException.class,
() -> bp.copy(lower, 0, lowerCopy, 0, lowerLength));
break;
}
bp.copy(lower, 0, lowerCopy, 0, lowerLength);
int middleOffset = RND.nextInt(1 + cap/2);
Buffer middle = buf.slice(middleOffset, lowerLength);
Buffer middleCopy = bp.create(lowerLength);
bp.copy(middle, 0, middleCopy, 0, lowerLength);
bp.put(lower, middle);
middle.flip();
assertTrue(bp.equals(lowerCopy, middle),
String.format("%d %s %d %d %d %d%n", SEED,
buf.getClass().getName(), cap,
lowerOffset, lowerLength, middleOffset));
bp.copy(lowerCopy, 0, buf, lowerOffset, lowerLength);
bp.copy(middleCopy, 0, buf, middleOffset, lowerLength);
bp.put(buf, lowerOffset, buf, middleOffset, lowerLength);
assertTrue(bp.equals(lowerCopy, middle),
String.format("%d %s %d %d %d %d%n", SEED,
buf.getClass().getName(), cap,
lowerOffset, lowerLength, middleOffset));
}
}
@ParameterizedTest
@MethodSource("proxyPairs")
public void testPairs(BufferProxy bp, BufferProxy sbp) throws Throwable {
for (int i = 0; i < ITERATIONS; i++) {
int cap = Math.max(4, RND.nextInt(MAX_CAPACITY));
int cap2 = cap/2;
Buffer buf = bp.create(cap);
int pos = RND.nextInt(Math.max(1, cap2));
buf.position(pos);
buf.mark();
int lim = pos + Math.max(1, cap - pos);
buf.limit(lim);
int scap = Math.max(buf.remaining(), RND.nextInt(1024));
Buffer src = sbp.create(scap);
int diff = scap - buf.remaining();
int spos = diff > 0 ? RND.nextInt(diff) : 0;
src.position(spos);
src.mark();
int slim = spos + buf.remaining();
src.limit(slim);
if (buf.isReadOnly()) {
assertThrows(ReadOnlyBufferException.class,
() -> bp.put(src, buf));
break;
}
Buffer backup = bp.create(slim - spos);
bp.copy(buf, pos, backup, 0, backup.capacity());
bp.put(src, buf);
buf.reset();
src.reset();
assertTrue(bp.equals(src, buf),
String.format("%d %s %d %d %d %s %d %d %d%n", SEED,
buf.getClass().getName(), cap, pos, lim,
src.getClass().getName(), scap, spos, slim));
src.clear();
buf.clear();
bp.copy(backup, 0, buf, pos, backup.capacity());
bp.put(src, spos, buf, pos, backup.capacity());
src.position(spos);
src.limit(slim);
buf.position(pos);
buf.limit(lim);
assertTrue(bp.equals(src, buf),
String.format("%d %s %d %d %d %s %d %d %d%n", SEED,
buf.getClass().getName(), cap, pos, lim,
src.getClass().getName(), scap, spos, slim));
}
}
}

View file

@ -0,0 +1,791 @@
/*
* Copyright (c) 2016, 2026, 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
* @summary Binary data and view tests for byte buffers
* @bug 8159257 8258955
* @run junit ByteBufferViews
*/
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.fail;
public class ByteBufferViews {
static final int SIZE = 32;
// List of buffer allocator functions
static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_ALLOCATE_FUNCTIONS = List.of(
// Heap
Map.entry("ByteBuffer.allocate(ba)",
size -> ByteBuffer.allocate(size)),
// Aligned
Map.entry("ByteBuffer.allocate(size).position(8)",
size -> ByteBuffer.allocate(size).position(8)),
Map.entry("ByteBuffer.allocate(size).position(8).slice()",
size -> ByteBuffer.allocate(size).position(8).slice()),
Map.entry("ByteBuffer.allocate(size).position(8).slice().duplicate()",
size -> ByteBuffer.allocate(size).position(8).slice().duplicate()),
Map.entry("ByteBuffer.allocate(size).slice(8,size-8)",
size -> ByteBuffer.allocate(size).slice(8,size-8)),
// Unaligned
Map.entry("ByteBuffer.allocate(size).position(1)",
size -> ByteBuffer.allocate(size).position(1)),
Map.entry("ByteBuffer.allocate(size).position(1).slice()",
size -> ByteBuffer.allocate(size).position(1).slice()),
Map.entry("ByteBuffer.allocate(size).position(1).slice().duplicate()",
size -> ByteBuffer.allocate(size).position(1).slice().duplicate()),
Map.entry("ByteBuffer.allocate(size).slice(1,size-1)",
size -> ByteBuffer.allocate(size).slice(1,size-1)),
// Off-heap
Map.entry("ByteBuffer.allocateDirect(size)",
size -> ByteBuffer.allocateDirect(size)),
// Aligned
Map.entry("ByteBuffer.allocateDirect(size).position(8)",
size -> ByteBuffer.allocateDirect(size).position(8)),
Map.entry("ByteBuffer.allocateDirect(size).position(8).slice()",
size -> ByteBuffer.allocateDirect(size).position(8).slice()),
Map.entry("ByteBuffer.allocateDirect(size).position(8).slice().duplicate()",
size -> ByteBuffer.allocateDirect(size).position(8).slice().duplicate()),
Map.entry("ByteBuffer.allocateDirect(size).slice(8,size-8)",
size -> ByteBuffer.allocateDirect(size).slice(8,size-8)),
// Unaligned
Map.entry("ByteBuffer.allocateDirect(size).position(1)",
size -> ByteBuffer.allocateDirect(size).position(1)),
Map.entry("ByteBuffer.allocateDirect(size).position(1).slice()",
size -> ByteBuffer.allocateDirect(size).position(1).slice()),
Map.entry("ByteBuffer.allocateDirect(size).position(1).slice().duplicate()",
size -> ByteBuffer.allocateDirect(size).position(1).slice().duplicate()),
Map.entry("ByteBuffer.allocateDirect(size).slice(1,size-1)",
size -> ByteBuffer.allocateDirect(size).slice(1,size-1))
);
// List of buffer byte order functions
static final List<Map.Entry<String, UnaryOperator<ByteBuffer>>> BYTE_BUFFER_ORDER_FUNCTIONS = List.of(
Map.entry("order(ByteOrder.BIG_ENDIAN)",
(ByteBuffer bb) -> bb.order(ByteOrder.BIG_ENDIAN)),
Map.entry("order(ByteOrder.LITTLE_ENDIAN)",
(ByteBuffer bb) -> bb.order(ByteOrder.LITTLE_ENDIAN))
);
// Produce a composition of allocation and byte order buffer functions
static List<Map.Entry<String, IntFunction<ByteBuffer>>> composeBufferFunctions(
List<Map.Entry<String, IntFunction<ByteBuffer>>> af,
List<Map.Entry<String, UnaryOperator<ByteBuffer>>> of) {
return af.stream().flatMap(afe -> of.stream().
map(ofe -> {
String s = afe.getKey() + "." + ofe.getKey();
IntFunction<ByteBuffer> f = size -> ofe.getValue().
apply(afe.getValue().apply(size));
return Map.entry(s, f);
})
).collect(Collectors.toList());
}
// List of buffer allocator functions to test
static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_FUNCTIONS =
composeBufferFunctions(BYTE_BUFFER_ALLOCATE_FUNCTIONS, BYTE_BUFFER_ORDER_FUNCTIONS);
// Creates a cross product of test arguments for
// buffer allocator functions and buffer view functions
static Stream<Arguments> product(List<? extends Map.Entry<String, ?>> la,
List<? extends Map.Entry<String, ?>> lb) {
return la.stream().flatMap(lae -> lb.stream().
map(lbe -> Arguments.of
(
lae.getKey() + " -> " + lbe.getKey(),
lae.getValue(),
lbe.getValue())
));
}
static void assertValues(int i, Object bValue, Object bbValue, ByteBuffer bb) {
if (!bValue.equals(bbValue)) {
fail(String.format("Values %s and %s differ at index %d for %s",
bValue, bbValue, i, bb));
}
}
static void assertValues(int i, Object bbValue, Object bvValue, ByteBuffer bb, Buffer bv) {
if (!bbValue.equals(bvValue)) {
fail(String.format("Values %s and %s differ at index %d for %s and %s",
bbValue, bvValue, i, bb, bv));
}
}
static ByteBuffer allocate(IntFunction<ByteBuffer> f) {
return allocate(f, i -> i);
}
static ByteBuffer allocate(IntFunction<ByteBuffer> f, IntUnaryOperator o) {
return fill(f.apply(SIZE), o);
}
static ByteBuffer fill(ByteBuffer bb, IntUnaryOperator o) {
for (int i = 0; i < bb.limit(); i++) {
bb.put(i, (byte) o.applyAsInt(i));
}
return bb;
}
public static Stream<Arguments> shortBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, ShortBuffer>>> bfs = List.of(
Map.entry("bb.asShortBuffer()",
bb -> bb.asShortBuffer()),
Map.entry("bb.asShortBuffer().slice()",
bb -> bb.asShortBuffer().slice()),
Map.entry("bb.asShortBuffer().slice(index,length)",
bb -> { var sb = bb.asShortBuffer();
sb = sb.slice(1, sb.limit() - 1);
bb.position(bb.position() + 2);
return sb; }),
Map.entry("bb.asShortBuffer().slice().duplicate()",
bb -> bb.asShortBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@ParameterizedTest
@MethodSource("shortBufferViews")
public void testShortGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, ShortBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
ShortBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
short fromBytes = getShortFromBytes(bb, o + i * 2);
short fromMethodView = bb.getShort(o + i * 2);
assertValues(i, fromBytes, fromMethodView, bb);
short fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
short v = getShortFromBytes(bb, o + i * 2);
short a = bb.getShort();
assertValues(i, v, a, bb);
short b = vb.get();
assertValues(i, a, b, bb, vb);
}
}
@ParameterizedTest
@MethodSource("shortBufferViews")
public void testShortPut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, ShortBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
ShortBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
short fromFilled = bbfilled.getShort(o + i * 2);
vb.put(i, fromFilled);
short fromMethodView = bb.getShort(o + i * 2);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
short fromFilled = bbfilled.getShort(o + i * 2);
vb.put(fromFilled);
short fromMethodView = bb.getShort();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
short fromFilled = bbfilled.getShort(o + i * 2);
bb.putShort(o + i * 2, fromFilled);
short fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
short fromFilled = bbfilled.getShort(o + i * 2);
bb.putShort(fromFilled);
short fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static short getShortFromBytes(ByteBuffer bb, int i) {
int a = bb.get(i) & 0xFF;
int b = bb.get(i + 1) & 0xFF;
if (bb.order() == ByteOrder.BIG_ENDIAN) {
return (short) ((a << 8) | b);
}
else {
return (short) ((b << 8) | a);
}
}
public static Stream<Arguments> charBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, CharBuffer>>> bfs = List.of(
Map.entry("bb.asCharBuffer()",
bb -> bb.asCharBuffer()),
Map.entry("bb.asCharBuffer().slice()",
bb -> bb.asCharBuffer().slice()),
Map.entry("bb.asCharBuffer().slice(index,length)",
bb -> { var cb = bb.asCharBuffer();
cb = cb.slice(1, cb.limit() - 1);
bb.position(bb.position() + 2);
return cb; }),
Map.entry("bb.asCharBuffer().slice().duplicate()",
bb -> bb.asCharBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@ParameterizedTest
@MethodSource("charBufferViews")
public void testCharGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, CharBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
CharBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
char fromBytes = getCharFromBytes(bb, o + i * 2);
char fromMethodView = bb.getChar(o + i * 2);
assertValues(i, fromBytes, fromMethodView, bb);
char fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
char fromBytes = getCharFromBytes(bb, o + i * 2);
char fromMethodView = bb.getChar();
assertValues(i, fromBytes, fromMethodView, bb);
char fromBufferView = vb.get();
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
}
@ParameterizedTest
@MethodSource("charBufferViews")
public void testCharPut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, CharBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
CharBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
char fromFilled = bbfilled.getChar(o + i * 2);
vb.put(i, fromFilled);
char fromMethodView = bb.getChar(o + i * 2);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
char fromFilled = bbfilled.getChar(o + i * 2);
vb.put(fromFilled);
char fromMethodView = bb.getChar();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
char fromFilled = bbfilled.getChar(o + i * 2);
bb.putChar(o + i * 2, fromFilled);
char fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
char fromFilled = bbfilled.getChar(o + i * 2);
bb.putChar(fromFilled);
char fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static char getCharFromBytes(ByteBuffer bb, int i) {
return (char) getShortFromBytes(bb, i);
}
public static Stream<Arguments> intBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, IntBuffer>>> bfs = List.of(
Map.entry("bb.asIntBuffer()",
bb -> bb.asIntBuffer()),
Map.entry("bb.asIntBuffer().slice()",
bb -> bb.asIntBuffer().slice()),
Map.entry("bb.asIntBuffer().slice(index,length)",
bb -> { var ib = bb.asIntBuffer();
ib = ib.slice(1, ib.limit() - 1);
bb.position(bb.position() + 4);
return ib; }),
Map.entry("bb.asIntBuffer().slice().duplicate()",
bb -> bb.asIntBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@ParameterizedTest
@MethodSource("intBufferViews")
public void testIntGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, IntBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
IntBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
int fromBytes = getIntFromBytes(bb, o + i * 4);
int fromMethodView = bb.getInt(o + i * 4);
assertValues(i, fromBytes, fromMethodView, bb);
int fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
int v = getIntFromBytes(bb, o + i * 4);
int a = bb.getInt();
assertValues(i, v, a, bb);
int b = vb.get();
assertValues(i, a, b, bb, vb);
}
}
@ParameterizedTest
@MethodSource("intBufferViews")
public void testIntPut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, IntBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
IntBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
int fromFilled = bbfilled.getInt(o + i * 4);
vb.put(i, fromFilled);
int fromMethodView = bb.getInt(o + i * 4);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
int fromFilled = bbfilled.getInt(o + i * 4);
vb.put(fromFilled);
int fromMethodView = bb.getInt();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
int fromFilled = bbfilled.getInt(o + i * 4);
bb.putInt(o + i * 4, fromFilled);
int fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
int fromFilled = bbfilled.getInt(o + i * 4);
bb.putInt(fromFilled);
int fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static int getIntFromBytes(ByteBuffer bb, int i) {
int a = bb.get(i) & 0xFF;
int b = bb.get(i + 1) & 0xFF;
int c = bb.get(i + 2) & 0xFF;
int d = bb.get(i + 3) & 0xFF;
if (bb.order() == ByteOrder.BIG_ENDIAN) {
return ((a << 24) | (b << 16) | (c << 8) | d);
}
else {
return ((d << 24) | (c << 16) | (b << 8) | a);
}
}
public static Stream<Arguments> longBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, LongBuffer>>> bfs = List.of(
Map.entry("bb.asLongBuffer()",
bb -> bb.asLongBuffer()),
Map.entry("bb.asLongBuffer().slice()",
bb -> bb.asLongBuffer().slice()),
Map.entry("bb.asLongBuffer().slice(index,length)",
bb -> { var lb = bb.asLongBuffer();
lb = lb.slice(1, lb.limit() - 1);
bb.position(bb.position() + 8);
return lb; }),
Map.entry("bb.asLongBuffer().slice().duplicate()",
bb -> bb.asLongBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@ParameterizedTest
@MethodSource("longBufferViews")
public void testLongGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, LongBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
LongBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
long fromBytes = getLongFromBytes(bb, o + i * 8);
long fromMethodView = bb.getLong(o + i * 8);
assertValues(i, fromBytes, fromMethodView, bb);
long fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
long v = getLongFromBytes(bb, o + i * 8);
long a = bb.getLong();
assertValues(i, v, a, bb);
long b = vb.get();
assertValues(i, a, b, bb, vb);
}
}
@ParameterizedTest
@MethodSource("longBufferViews")
public void testLongPut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, LongBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
LongBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
long fromFilled = bbfilled.getLong(o + i * 8);
vb.put(i, fromFilled);
long fromMethodView = bb.getLong(o + i * 8);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
long fromFilled = bbfilled.getLong(o + i * 8);
vb.put(fromFilled);
long fromMethodView = bb.getLong();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
long fromFilled = bbfilled.getLong(o + i * 8);
bb.putLong(o + i * 8, fromFilled);
long fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
long fromFilled = bbfilled.getLong(o + i * 8);
bb.putLong(fromFilled);
long fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static long getLongFromBytes(ByteBuffer bb, int i) {
long a = bb.get(i) & 0xFF;
long b = bb.get(i + 1) & 0xFF;
long c = bb.get(i + 2) & 0xFF;
long d = bb.get(i + 3) & 0xFF;
long e = bb.get(i + 4) & 0xFF;
long f = bb.get(i + 5) & 0xFF;
long g = bb.get(i + 6) & 0xFF;
long h = bb.get(i + 7) & 0xFF;
if (bb.order() == ByteOrder.BIG_ENDIAN) {
return ((a << 56) | (b << 48) | (c << 40) | (d << 32) |
(e << 24) | (f << 16) | (g << 8) | h);
}
else {
return ((h << 56) | (g << 48) | (f << 40) | (e << 32) |
(d << 24) | (c << 16) | (b << 8) | a);
}
}
public static Stream<Arguments> floatBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, FloatBuffer>>> bfs = List.of(
Map.entry("bb.asFloatBuffer()",
bb -> bb.asFloatBuffer()),
Map.entry("bb.asFloatBuffer().slice()",
bb -> bb.asFloatBuffer().slice()),
Map.entry("bb.asFloatBuffer().slice(index,length)",
bb -> { var fb = bb.asFloatBuffer();
fb = fb.slice(1, fb.limit() - 1);
bb.position(bb.position() + 4);
return fb; }),
Map.entry("bb.asFloatBuffer().slice().duplicate()",
bb -> bb.asFloatBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@ParameterizedTest
@MethodSource("floatBufferViews")
public void testFloatGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, FloatBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
FloatBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
float fromBytes = getFloatFromBytes(bb, o + i * 4);
float fromMethodView = bb.getFloat(o + i * 4);
assertValues(i, fromBytes, fromMethodView, bb);
float fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
float v = getFloatFromBytes(bb, o + i * 4);
float a = bb.getFloat();
assertValues(i, v, a, bb);
float b = vb.get();
assertValues(i, a, b, bb, vb);
}
}
@ParameterizedTest
@MethodSource("floatBufferViews")
public void testFloatPut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, FloatBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
FloatBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
float fromFilled = bbfilled.getFloat(o + i * 4);
vb.put(i, fromFilled);
float fromMethodView = bb.getFloat(o + i * 4);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
float fromFilled = bbfilled.getFloat(o + i * 4);
vb.put(fromFilled);
float fromMethodView = bb.getFloat();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
float fromFilled = bbfilled.getFloat(o + i * 4);
bb.putFloat(o + i * 4, fromFilled);
float fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
float fromFilled = bbfilled.getFloat(o + i * 4);
bb.putFloat(fromFilled);
float fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static float getFloatFromBytes(ByteBuffer bb, int i) {
return Float.intBitsToFloat(getIntFromBytes(bb, i));
}
public static Stream<Arguments> doubleBufferViews() {
List<Map.Entry<String, Function<ByteBuffer, DoubleBuffer>>> bfs = List.of(
Map.entry("bb.asDoubleBuffer()",
bb -> bb.asDoubleBuffer()),
Map.entry("bb.asDoubleBuffer().slice()",
bb -> bb.asDoubleBuffer().slice()),
Map.entry("bb.asDoubleBuffer().slice(index,length)",
bb -> { var db = bb.asDoubleBuffer();
db = db.slice(1, db.limit() - 1);
bb.position(bb.position() + 8);
return db; }),
Map.entry("bb.asDoubleBuffer().slice().duplicate()",
bb -> bb.asDoubleBuffer().slice().duplicate())
);
return product(BYTE_BUFFER_FUNCTIONS, bfs);
}
@MethodSource("doubleBufferViews")
public void testDoubleGet(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, DoubleBuffer> fbi) {
ByteBuffer bb = allocate(fbb);
DoubleBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
double fromBytes = getDoubleFromBytes(bb, o + i * 8);
double fromMethodView = bb.getDouble(o + i * 8);
assertValues(i, fromBytes, fromMethodView, bb);
double fromBufferView = vb.get(i);
assertValues(i, fromMethodView, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
double v = getDoubleFromBytes(bb, o + i * 8);
double a = bb.getDouble();
assertValues(i, v, a, bb);
double b = vb.get();
assertValues(i, a, b, bb, vb);
}
}
@ParameterizedTest
@MethodSource("doubleBufferViews")
public void testDoublePut(String desc, IntFunction<ByteBuffer> fbb,
Function<ByteBuffer, DoubleBuffer> fbi) {
ByteBuffer bbfilled = allocate(fbb);
ByteBuffer bb = allocate(fbb, i -> 0);
DoubleBuffer vb = fbi.apply(bb);
int o = bb.position();
for (int i = 0; i < vb.limit(); i++) {
double fromFilled = bbfilled.getDouble(o + i * 8);
vb.put(i, fromFilled);
double fromMethodView = bb.getDouble(o + i * 8);
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
double fromFilled = bbfilled.getDouble(o + i * 8);
vb.put(fromFilled);
double fromMethodView = bb.getDouble();
assertValues(i, fromFilled, fromMethodView, bb, vb);
}
fill(bb, i -> 0);
bb.clear().position(o);
vb.clear();
for (int i = 0; i < vb.limit(); i++) {
double fromFilled = bbfilled.getDouble(o + i * 8);
bb.putDouble(o + i * 8, fromFilled);
double fromBufferView = vb.get(i);
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
for (int i = 0; i < vb.limit(); i++) {
double fromFilled = bbfilled.getDouble(o + i * 8);
bb.putDouble(fromFilled);
double fromBufferView = vb.get();
assertValues(i, fromFilled, fromBufferView, bb, vb);
}
}
static double getDoubleFromBytes(ByteBuffer bb, int i) {
return Double.longBitsToDouble(getLongFromBytes(bb, i));
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2001, 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
* @summary Test charAt index checking
* @bug 4510323
*/
import java.nio.*;
public class CharAt {
public static void main (String[] args) {
CharSequence cs = CharBuffer.wrap("foo");
for (int i = 0; i < cs.length(); i++)
System.err.print(cs.charAt(i));
System.err.println();
}
}

View file

@ -0,0 +1,326 @@
/*
* Copyright (c) 2025, 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.
*/
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.PrimitiveIterator.OfInt;
import java.util.Random;
import jdk.test.lib.RandomFactory;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
/*
* @test
* @bug 8343110 8361299 8364345
* @key randomness
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @summary Tests CharBuffer implementations of CharSequence
* @run junit CharBufferAsCharSequenceTest
*/
public class CharBufferAsCharSequenceTest {
private static final Random RAND = RandomFactory.getRandom();
private static final int SIZE = RAND.nextInt(128, 1153);
private static char[] randomChars() {
char[] chars = new char[SIZE];
for (int i=0; i<SIZE; ++i) {
chars[i] = (char) RAND.nextInt();
}
return chars;
}
/**
* Randomly adjusts the position and limit such that the position will be in the
* first 1/4th and the limit in the last half.
*/
private static CharBuffer randomizeRange(CharBuffer cb) {
int mid = cb.capacity() >>> 1;
int start = RAND.nextInt(mid >> 1); // from 0 to 1/4
int end = RAND.nextInt(mid + 1, cb.capacity()); // from mid to capacity
cb.position(start);
cb.limit(end);
return cb;
}
/**
* Generates random content to use for populating <i>cb</i> then calling through
* to {@code addCases(String, char[], CharBuffer, List)}
*
* @param type String description of the type of CharBuffer under test.
* @param cb CharBuffer instance to populate as base of creating cases.
* @param cases The {@code List} to populate with the cases for use from
* {@link #charBufferArguments()}.
*/
private static void populateAndAddCases(String type, CharBuffer cb, List<Arguments> cases) {
assert cb.position() == 0 && cb.limit() == cb.capacity();
char[] buf = randomChars();
cb.put(buf);
cb.clear();
addCases(type, buf, cb, cases);
}
/**
* Adds 4 cases to <i>cases</i>.
* <ul>
* <li>Full use of cb</li>.
* <li>A duplicate of <i>cb</i> with a randomized position and limit. See
* {@code randomizeRange(CharBuffer)}
* <li>
* <li>A {@link CharBuffer#slice() sliced} copy of randomized range.</li>
* <li>A {@link CharBuffer#slice() sliced} copy of randomized range with a
* randomized position and limit.</li>
* </ul>
*/
private static void addCases(String type, char[] buf, CharBuffer cb, List<Arguments> cases) {
assert cb.position() == 0 && cb.limit() == cb.capacity();
cases.add(Arguments.of(cb, buf, 0, buf.length, type + " full"));
CharBuffer rndRange = randomizeRange(cb.duplicate());
cases.add(Arguments.of(rndRange, buf, rndRange.position(), rndRange.limit(),
type + " at " + rndRange.position() + " through " + rndRange.limit()));
cases.add(Arguments.of(rndRange.slice(), buf, rndRange.position(), rndRange.limit(),
type + " sliced at " + rndRange.position() + " through " + rndRange.limit()));
CharBuffer rndSlicedRange = randomizeRange(rndRange.slice());
cases.add(Arguments.of(rndSlicedRange,
buf,
rndRange.position() + rndSlicedRange.position(),
rndRange.position() + rndSlicedRange.limit(),
type + " sliced at " + rndRange.position() + " with position " +
rndSlicedRange.position() + " and limit " + rndSlicedRange.limit()));
}
/**
* Returns a {@code List} of {@link Arguments}, with each entry representing a
* test case scenario.
* <ul>
* <li>CharBuffer - the instance to be tested</li>
* <li>char[] - the data expected to be backing the current state of the CharBuffer</li>
* <li>int start - index (inclusive) into char[] where the CharBuffer should be positioned</li>
* <li>int stop - index (exclusive) into char[] where the CharBuffer should be limited</li>
* <li>String - description of the test scenario</li>
* </ul>
*
* Generates the following sets of arguments/test cases.
* <ul>
* <li>See {@code populateAndAddCases(String, CharBuffer, List)} for the
* following types:
* <ul>
* <li>HeapCharBuffer</i>
* <li>HeapByteBuffer Big Endian</i>
* <li>HeapByteBuffer Little Endian</i>
* <li>DirectByteBuffer Big Endian</i>
* <li>DirectByteBuffer Little Endian</i>
* </ul>
* </li>
* <li>Randomly generated content into {@link CharBuffer#wrap(CharSequence)
* StringCharBuffer} - see {@code addCases(String, char[], CharBuffer, List)}.
* <ul>
* <li>StringCharBuffer wrapping a {@code CharBuffer} created from
* {@link CharBuffer#wrap(char[])}</li>
* <li>StringCharBuffer wrapping a {@code String}</li>
* </ul>
* </li>
* </ul>
*/
static List<Arguments> charBufferArguments() {
List<Arguments> args = new ArrayList<>();
populateAndAddCases("HeapCharBuffer", CharBuffer.allocate(SIZE), args);
populateAndAddCases("HeapByteBuffer BE",
ByteBuffer.allocate(SIZE * 2).order(ByteOrder.BIG_ENDIAN).asCharBuffer(), args);
populateAndAddCases("HeapByteBuffer LE",
ByteBuffer.allocate(SIZE * 2).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(), args);
populateAndAddCases("DirectByteBuffer BE",
ByteBuffer.allocateDirect(SIZE * 2).order(ByteOrder.BIG_ENDIAN).asCharBuffer(), args);
populateAndAddCases("DirectByteBuffer LE",
ByteBuffer.allocateDirect(SIZE * 2).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(), args);
char[] randomChars = randomChars();
CharBuffer cb = CharBuffer.wrap(randomChars);
addCases("StringCharBuffer over CharBuffer", randomChars, CharBuffer.wrap(cb), args);
addCases("StringCharBuffer over String", randomChars, CharBuffer.wrap(new String(randomChars)), args);
return args;
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testToString(CharSequence actual, char[] expected, int start, int stop, String description) {
assertEquals(new String(expected, start, stop - start), actual.toString(), description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testLength(CharSequence actual, char[] expected, int start, int stop, String description) {
assertEquals(stop - start, actual.length(), description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsRange(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
int length = Math.min(10, stop - start - 1);
actual.getChars(1, length + 1, val, 3);
for (int i = 0; i < length; ++i) {
assertEquals(expected[i + start + 1], val[i + 3], "val at offset of " + i + " from " + description);
}
// test that calling getChars did not move the position
assertEquals(expected[start], actual.charAt(0), "first char after calling getChars: " + description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsAll(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[stop - start];
actual.getChars(0, val.length, val, 0);
for (int i = 0; i < val.length; ++i) {
assertEquals(expected[i + start], val[i], "val at offset of " + i + " from " + description);
}
// test that calling getChars did not move the position
assertEquals(expected[start], actual.charAt(0), "first char after calling getChars: " + description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsNegativeSrcBegin(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(-1, 4, val, 1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsNegativeSrcEnd(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(0, -4, val, 1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsSrcEndBeforeBegin(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(3, 2, val, 1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsNegativeDstBegin(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(1, 3, val, -1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsDstBeginOOB(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(1, 4, val, val.length + 1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsDstLengthOOB(CharSequence actual, char[] expected, int start, int stop, String description) {
char[] val = new char[16];
assertThrows(IndexOutOfBoundsException.class, () -> actual.getChars(1, 4, val, val.length - 2));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testGetCharsNullDst(CharSequence actual, char[] expected, int start, int stop, String description) {
assertThrows(NullPointerException.class, () -> actual.getChars(0, 1, null, 0));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testCharAt(CharSequence actual, char[] expected, int start, int stop, String description) {
for (int i = 0, j = stop - start; i < j; ++i) {
assertEquals(expected[start + i], actual.charAt(i), "chart at " + i + ": " + description);
}
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testCharAtNegativePos(CharSequence actual, char[] expected, int start, int stop, String description) {
assertThrows(IndexOutOfBoundsException.class, () -> actual.charAt(-1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testCharAtPosOOB(CharSequence actual, char[] expected, int start, int stop, String description) {
assertThrows(IndexOutOfBoundsException.class, () -> actual.charAt(stop - start + 1));
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testChars(CharSequence actual, char[] expected, int start, int stop, String description) {
OfInt chars = actual.chars().iterator();
for (int i = 0, j = stop - start; i < j; ++i) {
assertEquals(expected[start + i], (char) chars.nextInt(), "chart at " + i + ": " + description);
}
assertFalse(chars.hasNext(), "chars has more elements than expected " + description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testCodePoints(CharSequence actual, char[] expected, int start, int stop, String description) {
OfInt codePoints = actual.codePoints().iterator();
for (int i = 0, j = stop - start; i < j; ++i) {
char c1 = expected[start + i];
int expectedCodePoint = c1;
if (Character.isHighSurrogate(c1) && (i + 1) < j) {
char c2 = expected[start + i + 1];
if (Character.isLowSurrogate(c2)) {
expectedCodePoint = Character.toCodePoint(c1, c2);
++i;
}
}
assertEquals(expectedCodePoint, codePoints.nextInt(), "code point at " + i + ": " + description);
}
assertFalse(codePoints.hasNext(), "codePoints has more elements than expected " + description);
}
@ParameterizedTest(name="{4}")
@MethodSource("charBufferArguments")
void testSubSequence(CharSequence actual, char[] expected, int start, int stop, String description) {
int maxTests = Math.min(7, ((stop - start) >> 1) - 1);
for (int i = 0; i < maxTests; ++i) {
assertEquals(new String(expected, start + i, stop - start - (2 * i)),
actual.subSequence(i, actual.length() - i).toString(),
"subsequence at index " + i + " for " + description);
}
}
}

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2013, 2026, 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 8014854
* @summary Exercises CharBuffer#chars on each of the CharBuffer types
* @run junit Chars
* @key randomness
*/
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class Chars {
static final Random RAND = new Random();
static final int SIZE = 128 + RAND.nextInt(1024);
/**
* Randomize the char buffer's position and limit.
*/
static CharBuffer randomizeRange(CharBuffer cb) {
int mid = cb.capacity() >>> 1;
int start = RAND.nextInt(mid + 1); // from 0 to mid
int end = mid + RAND.nextInt(cb.capacity() - mid + 1); // from mid to capacity
cb.position(start);
cb.limit(end);
return cb;
}
/**
* Randomize the char buffer's contents, position and limit.
*/
static CharBuffer randomize(CharBuffer cb) {
while (cb.hasRemaining()) {
cb.put((char)RAND.nextInt());
}
return randomizeRange(cb);
}
/**
* Sums the remaining chars in the char buffer.
*/
static int intSum(CharBuffer cb) {
int sum = 0;
cb.mark();
while (cb.hasRemaining()) {
sum += cb.get();
}
cb.reset();
return sum;
}
/**
* Creates char buffers to test, adding them to the given list.
*/
static void addCases(CharBuffer cb, List<CharBuffer> buffers) {
randomize(cb);
buffers.add(cb);
buffers.add(cb.slice());
buffers.add(cb.duplicate());
buffers.add(cb.asReadOnlyBuffer());
buffers.add(randomizeRange(cb.slice()));
buffers.add(randomizeRange(cb.duplicate()));
buffers.add(randomizeRange(cb.asReadOnlyBuffer()));
}
private static Stream<Arguments> createCharBuffers() {
List<CharBuffer> buffers = new ArrayList<>();
// heap
addCases(CharBuffer.allocate(SIZE), buffers);
addCases(CharBuffer.wrap(new char[SIZE]), buffers);
addCases(ByteBuffer.allocate(SIZE*2).order(ByteOrder.BIG_ENDIAN).asCharBuffer(),
buffers);
addCases(ByteBuffer.allocate(SIZE*2).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(),
buffers);
// direct
addCases(ByteBuffer.allocateDirect(SIZE*2).order(ByteOrder.BIG_ENDIAN).asCharBuffer(),
buffers);
addCases(ByteBuffer.allocateDirect(SIZE*2).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(),
buffers);
// read-only buffer backed by a CharSequence
buffers.add(CharBuffer.wrap(randomize(CharBuffer.allocate(SIZE))));
List<Arguments> params = new ArrayList<Arguments>();
for (int i = 0; i < buffers.size(); i++) {
CharBuffer cb = buffers.get(i);
params.add((Arguments.of(cb.getClass().getName(), cb)));
}
return params.stream();
}
@ParameterizedTest
@MethodSource("createCharBuffers")
public void testChars(String type, CharBuffer cb) {
System.err.format("%s position=%d, limit=%d%n", type, cb.position(), cb.limit());
int expected = intSum(cb);
assertEquals(expected, cb.chars().sum());
assertEquals(expected, cb.chars().parallel().sum());
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2004, 2024, 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 5046110
* @summary Ensure that direct memory can be unreserved
* as the reserving thread sleeps
*
* @run main/othervm -Xmx16M Chew
*/
import java.nio.*;
public class Chew {
public static void main(String[] args) {
for (int i = 0; i < 64; i++)
ByteBuffer.allocateDirect(1 << 20);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
#warn This file is preprocessed before being compiled
import java.nio.*;
public class CopyDirect$Type$Memory
extends CopyDirectMemory
{
private static void init($Type$Buffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, ($type$)ic(i));
b.limit(n);
b.position(0);
}
private static void init($type$ [] a) {
for (int i = 0; i < a.length; i++)
a[i] = ($type$)ic(i + 1);
}
public static void test() {
#if[byte]
ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
#else[byte]
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
$Type$Buffer b = bb.as$Type$Buffer();
#end[byte]
init(b);
$type$ [] a = new $type$[b.capacity()];
init(a);
// copyFrom$Type$Array (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), ($type$)ic(i + 1));
// copyTo$Type$Array (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectByteMemory
extends CopyDirectMemory
{
private static void init(ByteBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (byte)ic(i));
b.limit(n);
b.position(0);
}
private static void init(byte [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (byte)ic(i + 1);
}
public static void test() {
ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
init(b);
byte [] a = new byte[b.capacity()];
init(a);
// copyFromByteArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (byte)ic(i + 1));
// copyToByteArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectCharMemory
extends CopyDirectMemory
{
private static void init(CharBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (char)ic(i));
b.limit(n);
b.position(0);
}
private static void init(char [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (char)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
CharBuffer b = bb.asCharBuffer();
init(b);
char [] a = new char[b.capacity()];
init(a);
// copyFromCharArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (char)ic(i + 1));
// copyToCharArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectDoubleMemory
extends CopyDirectMemory
{
private static void init(DoubleBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (double)ic(i));
b.limit(n);
b.position(0);
}
private static void init(double [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (double)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
DoubleBuffer b = bb.asDoubleBuffer();
init(b);
double [] a = new double[b.capacity()];
init(a);
// copyFromDoubleArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (double)ic(i + 1));
// copyToDoubleArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectFloatMemory
extends CopyDirectMemory
{
private static void init(FloatBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (float)ic(i));
b.limit(n);
b.position(0);
}
private static void init(float [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (float)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
FloatBuffer b = bb.asFloatBuffer();
init(b);
float [] a = new float[b.capacity()];
init(a);
// copyFromFloatArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (float)ic(i + 1));
// copyToFloatArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectIntMemory
extends CopyDirectMemory
{
private static void init(IntBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (int)ic(i));
b.limit(n);
b.position(0);
}
private static void init(int [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (int)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
IntBuffer b = bb.asIntBuffer();
init(b);
int [] a = new int[b.capacity()];
init(a);
// copyFromIntArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (int)ic(i + 1));
// copyToIntArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectLongMemory
extends CopyDirectMemory
{
private static void init(LongBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (long)ic(i));
b.limit(n);
b.position(0);
}
private static void init(long [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (long)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
LongBuffer b = bb.asLongBuffer();
init(b);
long [] a = new long[b.capacity()];
init(a);
// copyFromLongArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (long)ic(i + 1));
// copyToLongArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2002, 2016, 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
* @summary Test view buffer bulk operations for large buffers.
* @bug 4463011
*
* @modules java.base/jdk.internal.misc
* @build Basic
* @run main CopyDirectMemory
*/
import java.nio.*;
public class CopyDirectMemory
extends Basic
{
public static void main(String [] args) {
CopyDirectByteMemory.test();
CopyDirectCharMemory.test();
CopyDirectShortMemory.test();
CopyDirectIntMemory.test();
CopyDirectLongMemory.test();
CopyDirectFloatMemory.test();
CopyDirectDoubleMemory.test();
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2002, 2007, 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.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class CopyDirectShortMemory
extends CopyDirectMemory
{
private static void init(ShortBuffer b) {
int n = b.capacity();
b.clear();
for (int i = 0; i < n; i++)
b.put(i, (short)ic(i));
b.limit(n);
b.position(0);
}
private static void init(short [] a) {
for (int i = 0; i < a.length; i++)
a[i] = (short)ic(i + 1);
}
public static void test() {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
ShortBuffer b = bb.asShortBuffer();
init(b);
short [] a = new short[b.capacity()];
init(a);
// copyFromShortArray (a -> b)
b.put(a);
for (int i = 0; i < a.length; i++)
ck(b, b.get(i), (short)ic(i + 1));
// copyToShortArray (b -> a)
init(b);
init(a);
b.get(a);
for (int i = 0; i < a.length; i++)
if (a[i] != b.get(i))
fail("Copy failed at " + i + ": '"
+ a[i] + "' != '" + b.get(i) + "'");
}
}

View file

@ -0,0 +1,174 @@
/*
* 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=128m -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 1MB)</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=128m 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_000d * 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(1000L);
}
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);
}
}
}

View file

@ -0,0 +1,722 @@
/*
* Copyright (c) 2017, 2026, 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.
*/
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.MappedByteBuffer;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.LongFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.StandardOpenOption.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*
* @test
* @bug 8193085 8199773
* @summary tests for buffer equals and compare
* @run junit EqualsCompareTest
*/
public class EqualsCompareTest {
// Maximum width in bits
static final int MAX_WIDTH = 512;
static final Map<Class, Integer> typeToWidth;
static {
typeToWidth = new HashMap<>();
typeToWidth.put(byte.class, Byte.SIZE);
typeToWidth.put(short.class, Short.SIZE);
typeToWidth.put(char.class, Character.SIZE);
typeToWidth.put(int.class, Integer.SIZE);
typeToWidth.put(long.class, Long.SIZE);
typeToWidth.put(float.class, Float.SIZE);
typeToWidth.put(double.class, Double.SIZE);
}
static int arraySizeFor(Class<?> type) {
assert type.isPrimitive();
return 4 * MAX_WIDTH / typeToWidth.get(type);
}
enum BufferKind {
HEAP,
HEAP_VIEW,
DIRECT;
}
static abstract class BufferType<T extends Buffer, E> {
final BufferKind k;
final Class<?> bufferType;
final Class<?> elementType;
final MethodHandle eq;
final MethodHandle cmp;
final MethodHandle mismtch;
final MethodHandle getter;
final MethodHandle setter;
BufferType(BufferKind k, Class<T> bufferType, Class<?> elementType) {
this.k = k;
this.bufferType = bufferType;
this.elementType = elementType;
var lookup = MethodHandles.lookup();
try {
eq = lookup.findVirtual(bufferType, "equals", MethodType.methodType(boolean.class, Object.class));
cmp = lookup.findVirtual(bufferType, "compareTo", MethodType.methodType(int.class, bufferType));
mismtch = lookup.findVirtual(bufferType, "mismatch", MethodType.methodType(int.class, bufferType));
getter = lookup.findVirtual(bufferType, "get", MethodType.methodType(elementType, int.class));
setter = lookup.findVirtual(bufferType, "put", MethodType.methodType(bufferType, int.class, elementType));
}
catch (Exception e) {
throw new AssertionError(e);
}
}
@Override
public String toString() {
return bufferType.getName() + " " + k;
}
T construct(int length) {
return construct(length, ByteOrder.BIG_ENDIAN);
}
abstract T construct(int length, ByteOrder bo);
@SuppressWarnings("unchecked")
T slice(T a, int from, int to, boolean dupOtherwiseSlice) {
a = (T) a.position(from).limit(to);
return (T) (dupOtherwiseSlice ? a.duplicate() : a.slice());
}
@SuppressWarnings("unchecked")
E get(T a, int i) {
try {
return (E) getter.invoke(a, i);
}
catch (RuntimeException | Error e) {
throw e;
}
catch (Throwable t) {
throw new Error(t);
}
}
void set(T a, int i, Object v) {
try {
setter.invoke(a, i, convert(v));
}
catch (RuntimeException | Error e) {
throw e;
}
catch (Throwable t) {
throw new Error(t);
}
}
abstract Object convert(Object o);
boolean equals(T a, T b) {
try {
return (boolean) eq.invoke(a, b);
}
catch (RuntimeException | Error e) {
throw e;
}
catch (Throwable t) {
throw new Error(t);
}
}
int compare(T a, T b) {
try {
return (int) cmp.invoke(a, b);
}
catch (RuntimeException | Error e) {
throw e;
}
catch (Throwable t) {
throw new Error(t);
}
}
boolean pairWiseEquals(T a, T b) {
if (a.remaining() != b.remaining())
return false;
int p = a.position();
for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--)
if (!get(a, i).equals(get(b, j)))
return false;
return true;
}
int mismatch(T a, T b) {
try {
return (int) mismtch.invoke(a, b);
}
catch (RuntimeException | Error e) {
throw e;
}
catch (Throwable t) {
throw new Error(t);
}
}
static class Bytes extends BufferType<ByteBuffer, Byte> {
Bytes(BufferKind k) {
super(k, ByteBuffer.class, byte.class);
}
@Override
ByteBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length).order(bo);
default:
case HEAP_VIEW:
case HEAP:
return ByteBuffer.allocate(length).order(bo);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? ((Integer) o).byteValue()
: o;
}
}
static class Chars extends BufferType<CharBuffer, Character> {
Chars(BufferKind k) {
super(k, CharBuffer.class, char.class);
}
@Override
CharBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Character.BYTES).
order(bo).
asCharBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Character.BYTES).
order(bo).
asCharBuffer();
default:
case HEAP:
return CharBuffer.allocate(length);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? (char) ((Integer) o).intValue()
: o;
}
CharBuffer transformToStringBuffer(CharBuffer c) {
char[] chars = new char[c.remaining()];
c.get(chars);
return CharBuffer.wrap(new String(chars));
}
}
static class Shorts extends BufferType<ShortBuffer, Short> {
Shorts(BufferKind k) {
super(k, ShortBuffer.class, short.class);
}
@Override
ShortBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Short.BYTES).
order(bo).
asShortBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Short.BYTES).
order(bo).
asShortBuffer();
default:
case HEAP:
return ShortBuffer.allocate(length);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? ((Integer) o).shortValue()
: o;
}
}
static class Ints extends BufferType<IntBuffer, Integer> {
Ints(BufferKind k) {
super(k, IntBuffer.class, int.class);
}
@Override
IntBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Integer.BYTES).
order(bo).
asIntBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Integer.BYTES).
order(bo).
asIntBuffer();
default:
case HEAP:
return IntBuffer.allocate(length);
}
}
Object convert(Object o) {
return o;
}
}
static class Floats extends BufferType<FloatBuffer, Float> {
Floats(BufferKind k) {
super(k, FloatBuffer.class, float.class);
}
@Override
FloatBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Float.BYTES).
order(bo).
asFloatBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Float.BYTES).
order(bo).
asFloatBuffer();
default:
case HEAP:
return FloatBuffer.allocate(length);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? ((Integer) o).floatValue()
: o;
}
@Override
boolean pairWiseEquals(FloatBuffer a, FloatBuffer b) {
if (a.remaining() != b.remaining())
return false;
int p = a.position();
for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) {
float av = a.get(i);
float bv = b.get(j);
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
return false;
}
return true;
}
}
static class Longs extends BufferType<LongBuffer, Long> {
Longs(BufferKind k) {
super(k, LongBuffer.class, long.class);
}
@Override
LongBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Long.BYTES).
order(bo).
asLongBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Long.BYTES).
order(bo).
asLongBuffer();
default:
case HEAP:
return LongBuffer.allocate(length);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? ((Integer) o).longValue()
: o;
}
}
static class Doubles extends BufferType<DoubleBuffer, Double> {
Doubles(BufferKind k) {
super(k, DoubleBuffer.class, double.class);
}
@Override
DoubleBuffer construct(int length, ByteOrder bo) {
switch (k) {
case DIRECT:
return ByteBuffer.allocateDirect(length * Double.BYTES).
order(bo).
asDoubleBuffer();
case HEAP_VIEW:
return ByteBuffer.allocate(length * Double.BYTES).
order(bo).
asDoubleBuffer();
default:
case HEAP:
return DoubleBuffer.allocate(length);
}
}
@Override
Object convert(Object o) {
return o instanceof Integer
? ((Integer) o).doubleValue()
: o;
}
@Override
boolean pairWiseEquals(DoubleBuffer a, DoubleBuffer b) {
if (a.remaining() != b.remaining())
return false;
int p = a.position();
for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) {
double av = a.get(i);
double bv = b.get(j);
if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
return false;
}
return true;
}
}
}
public static Stream<BufferType> bufferTypesSource() {
return Stream.of
(new BufferType.Bytes(BufferKind.HEAP),
new BufferType.Bytes(BufferKind.DIRECT),
new BufferType.Chars(BufferKind.HEAP),
new BufferType.Chars(BufferKind.HEAP_VIEW),
new BufferType.Chars(BufferKind.DIRECT),
new BufferType.Shorts(BufferKind.HEAP),
new BufferType.Shorts(BufferKind.HEAP_VIEW),
new BufferType.Shorts(BufferKind.DIRECT),
new BufferType.Ints(BufferKind.HEAP),
new BufferType.Ints(BufferKind.HEAP_VIEW),
new BufferType.Ints(BufferKind.DIRECT),
new BufferType.Floats(BufferKind.HEAP),
new BufferType.Floats(BufferKind.HEAP_VIEW),
new BufferType.Floats(BufferKind.DIRECT),
new BufferType.Longs(BufferKind.HEAP),
new BufferType.Longs(BufferKind.HEAP_VIEW),
new BufferType.Longs(BufferKind.DIRECT),
new BufferType.Doubles(BufferKind.HEAP),
new BufferType.Doubles(BufferKind.HEAP_VIEW),
new BufferType.Doubles(BufferKind.DIRECT));
}
public static Stream<Arguments> floatBufferTypesSource() {
LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
LongFunction<Object> bToD = Double::longBitsToDouble;
return Stream.of
(// canonical and non-canonical NaNs
// If conversion is a signalling NaN it may be subject to conversion to a
// quiet NaN on some processors, even if a copy is performed
// The tests assume that if conversion occurs it does not convert to the
// canonical NaN
Arguments.of(new BufferType.Floats(BufferKind.HEAP), 0x7fc00000L, 0x7f800001L, bTof),
Arguments.of(new BufferType.Floats(BufferKind.HEAP_VIEW), 0x7fc00000L, 0x7f800001L, bTof),
Arguments.of(new BufferType.Floats(BufferKind.DIRECT), 0x7fc00000L, 0x7f800001L, bTof),
Arguments.of(new BufferType.Doubles(BufferKind.HEAP), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD),
Arguments.of(new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD),
Arguments.of(new BufferType.Doubles(BufferKind.DIRECT), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD),
// +0.0 and -0.0
Arguments.of(new BufferType.Floats(BufferKind.HEAP), 0x0L, 0x80000000L, bTof),
Arguments.of(new BufferType.Floats(BufferKind.HEAP_VIEW), 0x0L, 0x80000000L, bTof),
Arguments.of(new BufferType.Floats(BufferKind.DIRECT), 0x0L, 0x80000000L, bTof),
Arguments.of(new BufferType.Doubles(BufferKind.HEAP), 0x0L, 0x8000000000000000L, bToD),
Arguments.of(new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x0L, 0x8000000000000000L, bToD),
Arguments.of(new BufferType.Doubles(BufferKind.DIRECT), 0x0L, 0x8000000000000000L, bToD));
}
public static Stream<Arguments> charBufferTypesSource() {
return Stream.of
(Arguments.of(new BufferType.Chars(BufferKind.HEAP)),
Arguments.of(new BufferType.Chars(BufferKind.HEAP_VIEW)),
Arguments.of(new BufferType.Chars(BufferKind.DIRECT)));
}
// Tests all primitive buffers
@ParameterizedTest
@MethodSource("bufferTypesSource")
<E>
void testBuffers(BufferType<Buffer, E> bufferType) {
// Test with buffers of the same byte order (BE)
BiFunction<BufferType<Buffer, E>, Integer, Buffer> constructor = (at, s) -> {
Buffer a = at.construct(s);
for (int x = 0; x < s; x++) {
at.set(a, x, x % 8);
}
return a;
};
testBufferType(bufferType, constructor, constructor);
// Test with buffers of different byte order
if (bufferType.elementType != byte.class &&
(bufferType.k == BufferKind.HEAP_VIEW ||
bufferType.k == BufferKind.DIRECT)) {
BiFunction<BufferType<Buffer, E>, Integer, Buffer> leConstructor = (at, s) -> {
Buffer a = at.construct(s, ByteOrder.LITTLE_ENDIAN);
for (int x = 0; x < s; x++) {
at.set(a, x, x % 8);
}
return a;
};
testBufferType(bufferType, constructor, leConstructor);
}
}
// Tests float and double buffers with edge-case values (NaN, -0.0, +0.0)
@ParameterizedTest
@MethodSource("floatBufferTypesSource")
public void testFloatBuffers(
BufferType<Buffer, Float> bufferType,
long rawBitsA, long rawBitsB,
LongFunction<Object> bitsToFloat) {
Object av = bitsToFloat.apply(rawBitsA);
Object bv = bitsToFloat.apply(rawBitsB);
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> allAs = (at, s) -> {
Buffer b = at.construct(s);
for (int x = 0; x < s; x++) {
at.set(b, x, av);
}
return b;
};
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> allBs = (at, s) -> {
Buffer b = at.construct(s);
for (int x = 0; x < s; x++) {
at.set(b, x, bv);
}
return b;
};
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> halfBs = (at, s) -> {
Buffer b = at.construct(s);
for (int x = 0; x < s / 2; x++) {
at.set(b, x, bv);
}
for (int x = s / 2; x < s; x++) {
at.set(b, x, 1);
}
return b;
};
// Sanity check
int size = arraySizeFor(bufferType.elementType);
assertTrue(bufferType.pairWiseEquals(allAs.apply(bufferType, size),
allBs.apply(bufferType, size)));
assertTrue(bufferType.equals(allAs.apply(bufferType, size),
allBs.apply(bufferType, size)));
testBufferType(bufferType, allAs, allBs);
testBufferType(bufferType, allAs, halfBs);
}
// Tests CharBuffer for region sources and CharSequence sources
@ParameterizedTest
@MethodSource("charBufferTypesSource")
public void testCharBuffers(BufferType.Chars charBufferType) {
BiFunction<BufferType.Chars, Integer, CharBuffer> constructor = (at, s) -> {
CharBuffer a = at.construct(s);
for (int x = 0; x < s; x++) {
at.set(a, x, x % 8);
}
return a;
};
BiFunction<BufferType.Chars, Integer, CharBuffer> constructorX = constructor.
andThen(charBufferType::transformToStringBuffer);
testBufferType(charBufferType, constructor, constructorX);
}
<B extends Buffer, E, BT extends BufferType<B, E>>
void testBufferType(BT bt,
BiFunction<BT, Integer, B> aConstructor,
BiFunction<BT, Integer, B> bConstructor) {
int n = arraySizeFor(bt.elementType);
for (boolean dupOtherwiseSlice : new boolean[]{ false, true }) {
for (int s : ranges(0, n)) {
B a = aConstructor.apply(bt, s);
B b = bConstructor.apply(bt, s);
for (int aFrom : ranges(0, s)) {
for (int aTo : ranges(aFrom, s)) {
int aLength = aTo - aFrom;
B as = aLength != s
? bt.slice(a, aFrom, aTo, dupOtherwiseSlice)
: a;
for (int bFrom : ranges(0, s)) {
for (int bTo : ranges(bFrom, s)) {
int bLength = bTo - bFrom;
B bs = bLength != s
? bt.slice(b, bFrom, bTo, dupOtherwiseSlice)
: b;
boolean eq = bt.pairWiseEquals(as, bs);
assertEquals(eq, bt.equals(as, bs));
assertEquals(eq, bt.equals(bs, as));
if (eq) {
assertEquals(0, bt.compare(as, bs));
assertEquals(0, bt.compare(bs, as));
// If buffers are equal, there shall be no mismatch
assertEquals(-1, bt.mismatch(as, bs));
assertEquals(-1, bt.mismatch(bs, as));
}
else {
int aCb = bt.compare(as, bs);
int bCa = bt.compare(bs, as);
int v = Integer.signum(aCb) * Integer.signum(bCa);
assertEquals(-1, v);
int aMs = bt.mismatch(as, bs);
int bMs = bt.mismatch(bs, as);
assertNotEquals(-1, aMs);
assertEquals(bMs, aMs);
}
}
}
if (aLength > 0 && !a.isReadOnly()) {
for (int i = aFrom; i < aTo; i++) {
B c = aConstructor.apply(bt, a.capacity());
B cs = aLength != s
? bt.slice(c, aFrom, aTo, dupOtherwiseSlice)
: c;
// Create common prefix with a length of i - aFrom
bt.set(c, i, -1);
assertFalse(bt.equals(c, a));
int cCa = bt.compare(cs, as);
int aCc = bt.compare(as, cs);
int v = Integer.signum(cCa) * Integer.signum(aCc);
assertEquals(-1, v);
int cMa = bt.mismatch(cs, as);
int aMc = bt.mismatch(as, cs);
assertEquals(aMc, cMa);
assertEquals(i - aFrom, cMa);
}
}
}
}
}
}
}
static int[] ranges(int from, int to) {
int width = to - from;
switch (width) {
case 0:
return new int[]{};
case 1:
return new int[]{from, to};
case 2:
return new int[]{from, from + 1, to};
case 3:
return new int[]{from, from + 1, from + 2, to};
default:
return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
.filter(i -> i >= from && i <= to)
.distinct().toArray();
}
}
@Test
void testHashCode() throws IOException {
byte[] bytes = "hello world".getBytes(UTF_8);
Path path = Files.createTempFile("", "");
Files.write(path, bytes);
try (FileChannel fc = FileChannel.open(path, READ, DELETE_ON_CLOSE)) {
MappedByteBuffer one = fc.map(FileChannel.MapMode.READ_ONLY, 0, bytes.length);
ByteBuffer two = ByteBuffer.wrap(bytes);
assertEquals(two, one);
assertEquals(two.hashCode(), one.hashCode());
}
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2002, 2025, 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 4627316 6743526
* @summary Test option to limit direct memory allocation
* @library /test/lib
*
* @summary Test: memory is properly limited using multiple buffers
* @run main/othervm -XX:MaxDirectMemorySize=10 LimitDirectMemory true 10 1
* @run main/othervm -XX:MaxDirectMemorySize=1k LimitDirectMemory true 1k 100
* @run main/othervm -XX:MaxDirectMemorySize=10m LimitDirectMemory true 10m 10m
*
* @summary Test: We can increase the amount of available memory
* @run main/othervm -XX:MaxDirectMemorySize=65M LimitDirectMemory false 64M 65M
*
* @summary Test: Exactly the default amount of memory is available
* @run main/othervm LimitDirectMemory false 10 1
* @run main/othervm -Xmx64m LimitDirectMemory false 0 DEFAULT
* @run main/othervm -Xmx64m LimitDirectMemory true 0 DEFAULT+1
*
* @summary Test: We should be able to eliminate direct memory allocation entirely
* @run main/othervm -XX:MaxDirectMemorySize=0 LimitDirectMemory true 0 1
*
* @summary Test: Setting the system property should not work so we should be able
* to allocate the default amount
* @run main/othervm -Dsun.nio.MaxDirectMemorySize=1K -Xmx64m
* LimitDirectMemory false DEFAULT-1 DEFAULT/2
*/
import java.nio.ByteBuffer;
import java.util.Properties;
public class LimitDirectMemory {
private static final int K = 1024;
public static void main(String [] args) throws Exception {
if (args.length < 2) {
throw new IllegalArgumentException("Usage: "
+ "java LimitDirectMemory"
+ " <OOME_expected(true|false)>"
+ " <fill_direct_memory>"
+ " <size_per_buffer>");
}
boolean throwp = parseThrow(args[0]);
int size = parseSize(args[1]);
int incr = (args.length > 2 ? parseSize(args[2]) : size);
Properties p = System.getProperties();
if (p.getProperty("sun.nio.MaxDirectMemorySize") != null)
throw new RuntimeException("sun.nio.MaxDirectMemorySize defined");
ByteBuffer [] b = new ByteBuffer[K];
// Fill up most/all of the direct memory
int i = 0;
while (size >= incr) {
b[i++] = ByteBuffer.allocateDirect(incr);
size -= incr;
}
if (throwp) {
try {
b[i] = ByteBuffer.allocateDirect(incr);
throw new RuntimeException("OutOfMemoryError not thrown: "
+ incr);
} catch (OutOfMemoryError e) {
e.printStackTrace(System.out);
System.out.println("OK - Error thrown as expected ");
}
} else {
b[i] = ByteBuffer.allocateDirect(incr);
System.out.println("OK - Error not thrown");
}
}
private static boolean parseThrow(String s) {
if (s.equals("true")) return true;
if (s.equals("false")) return false;
throw new RuntimeException("Unrecognized expectation: " + s);
}
private static int parseSize(String size) throws Exception {
if (size.equals("DEFAULT"))
return (int)Runtime.getRuntime().maxMemory();
if (size.equals("DEFAULT+1"))
return (int)Runtime.getRuntime().maxMemory() + 1;
if (size.equals("DEFAULT+1M"))
return (int)Runtime.getRuntime().maxMemory() + (1 << 20);
if (size.equals("DEFAULT-1"))
return (int)Runtime.getRuntime().maxMemory() - 1;
if (size.equals("DEFAULT/2"))
return (int)Runtime.getRuntime().maxMemory() / 2;
int idx = 0, len = size.length();
for (int i = 0; i < len; i++) {
if (Character.isDigit(size.charAt(i))) idx++;
else break;
}
if (idx == 0)
throw new RuntimeException("No digits detected: " + size);
int result = Integer.parseInt(size.substring(0, idx));
if (idx < len) {
for (int i = idx; i < len; i++) {
switch(size.charAt(i)) {
case 'T': case 't': result *= K; // fall through
case 'G': case 'g': result *= K; // fall through
case 'M': case 'm': result *= K; // fall through
case 'K': case 'k': result *= K;
break;
default:
throw new RuntimeException("Unrecognized size: " + size);
}
}
}
return result;
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, 2025, 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 4627316 6743526
* @summary Test option to limit direct memory allocation,
* various bad values fail to launch the VM
* @library /test/lib
* @build jdk.test.lib.Utils
* jdk.test.lib.Asserts
* jdk.test.lib.JDKToolFinder
* jdk.test.lib.JDKToolLauncher
* jdk.test.lib.Platform
* jdk.test.lib.process.*
*
* @run main LimitDirectMemoryNegativeTest foo
* @run main LimitDirectMemoryNegativeTest 10kmt
* @run main LimitDirectMemoryNegativeTest -1
*/
import jdk.test.lib.process.ProcessTools;
public class LimitDirectMemoryNegativeTest {
private static final String ERR = "Improperly specified VM option 'MaxDirectMemorySize=";
public static void main(String[] args) throws Exception {
if (args.length != 1) {
throw new IllegalArgumentException("missing size argument");
}
int exitCode = ProcessTools.executeTestJava(
"-XX:MaxDirectMemorySize=" + args[0],
LimitDirectMemoryNegativeTest.class.getName())
.shouldContain(ERR + args[0])
.getExitValue();
if (exitCode != 1) {
throw new RuntimeException("Unexpected exit code: " + exitCode);
}
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
#warn This file is preprocessed before being compiled
import java.nio.*;
public class Order$Type$ extends Order {
private static void ck$Type$Buffer($Type$Buffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
#if[char]
ck(buf.subSequence(buf.position(), buf.remaining()).order(), expected);
ck(buf.subSequence(buf.position(), buf.position()).order(), expected);
#end[char]
}
static void ck$Type$Buffer() {
$type$[] array = new $type$[LENGTH];
$Type$Buffer buf = $Type$Buffer.wrap(array);
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
buf = $Type$Buffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
buf = $Type$Buffer.allocate(LENGTH);
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
#if[char]
buf = $Type$Buffer.wrap("abcdefghijk");
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
buf = $Type$Buffer.wrap("abcdefghijk", 0, 5);
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
buf = $Type$Buffer.wrap(array).subSequence(0, LENGTH);
ck(buf.order(), nord);
ck$Type$Buffer(buf, nord);
buf = ByteBuffer.wrap(new byte[LENGTH]).as$Type$Buffer();
ck(buf.order(), be);
ck$Type$Buffer(buf, be);
buf = ByteBuffer.wrap(new byte[LENGTH]).order(le).as$Type$Buffer();
ck(buf.order(), le);
ck$Type$Buffer(buf, le);
#end[char]
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2001, 2016, 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 8065570
* @summary Unit test for X-Buffer.order methods
*/
import java.nio.*;
public class Order {
static final ByteOrder be = ByteOrder.BIG_ENDIAN;
static final ByteOrder le = ByteOrder.LITTLE_ENDIAN;
static final ByteOrder nord = ByteOrder.nativeOrder();
protected static final int LENGTH = 16;
static void ck(ByteOrder ord, ByteOrder expected) {
if (ord != expected)
throw new RuntimeException("Got " + ord + ", expected " + expected);
}
private static void ckViews(ByteBuffer bb) {
ck(bb.asCharBuffer().order(), bb.order());
ck(bb.asShortBuffer().order(), bb.order());
ck(bb.asIntBuffer().order(), bb.order());
ck(bb.asLongBuffer().order(), bb.order());
ck(bb.asFloatBuffer().order(), bb.order());
ck(bb.asDoubleBuffer().order(), bb.order());
}
private static void ckCopyViews(ByteBuffer bb) {
ck(bb.asReadOnlyBuffer().order(), be);
ck(bb.duplicate().order(), be);
ck(bb.slice().order(), be);
}
private static void ckByteBuffer(ByteBuffer bb) {
ckViews(bb);
ckCopyViews(bb);
bb.order(be);
ckViews(bb);
ckCopyViews(bb);
bb.order(le);
ckViews(bb);
ckCopyViews(bb);
}
public static void main(String args[]) throws Exception {
ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(), be);
ck(ByteBuffer.wrap(new byte[LENGTH]).order(), be);
ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(be).order(), be);
ck(ByteBuffer.wrap(new byte[LENGTH]).order(be).order(), be);
ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(le).order(), le);
ck(ByteBuffer.wrap(new byte[LENGTH]).order(le).order(), le);
ck(ByteBuffer.allocate(LENGTH).order(), be);
ck(ByteBuffer.allocateDirect(LENGTH).order(), be);
ck(ByteBuffer.allocate(LENGTH).order(be).order(), be);
ck(ByteBuffer.allocate(LENGTH).order(le).order(), le);
ck(ByteBuffer.allocateDirect(LENGTH).order(be).order(), be);
ck(ByteBuffer.allocateDirect(LENGTH).order(le).order(), le);
ckByteBuffer(ByteBuffer.allocate(LENGTH));
ckByteBuffer(ByteBuffer.allocateDirect(LENGTH));
OrderChar.ckCharBuffer();
OrderShort.ckShortBuffer();
OrderInt.ckIntBuffer();
OrderLong.ckLongBuffer();
OrderFloat.ckFloatBuffer();
OrderDouble.ckDoubleBuffer();
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderChar extends Order {
private static void ckCharBuffer(CharBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
ck(buf.subSequence(buf.position(), buf.remaining()).order(), expected);
ck(buf.subSequence(buf.position(), buf.position()).order(), expected);
}
static void ckCharBuffer() {
char[] array = new char[LENGTH];
CharBuffer buf = CharBuffer.wrap(array);
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = CharBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = CharBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = CharBuffer.wrap("abcdefghijk");
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = CharBuffer.wrap("abcdefghijk", 0, 5);
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = CharBuffer.wrap(array).subSequence(0, LENGTH);
ck(buf.order(), nord);
ckCharBuffer(buf, nord);
buf = ByteBuffer.wrap(new byte[LENGTH]).asCharBuffer();
ck(buf.order(), be);
ckCharBuffer(buf, be);
buf = ByteBuffer.wrap(new byte[LENGTH]).order(le).asCharBuffer();
ck(buf.order(), le);
ckCharBuffer(buf, le);
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderDouble extends Order {
private static void ckDoubleBuffer(DoubleBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
}
static void ckDoubleBuffer() {
double[] array = new double[LENGTH];
DoubleBuffer buf = DoubleBuffer.wrap(array);
ck(buf.order(), nord);
ckDoubleBuffer(buf, nord);
buf = DoubleBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckDoubleBuffer(buf, nord);
buf = DoubleBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckDoubleBuffer(buf, nord);
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderFloat extends Order {
private static void ckFloatBuffer(FloatBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
}
static void ckFloatBuffer() {
float[] array = new float[LENGTH];
FloatBuffer buf = FloatBuffer.wrap(array);
ck(buf.order(), nord);
ckFloatBuffer(buf, nord);
buf = FloatBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckFloatBuffer(buf, nord);
buf = FloatBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckFloatBuffer(buf, nord);
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderInt extends Order {
private static void ckIntBuffer(IntBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
}
static void ckIntBuffer() {
int[] array = new int[LENGTH];
IntBuffer buf = IntBuffer.wrap(array);
ck(buf.order(), nord);
ckIntBuffer(buf, nord);
buf = IntBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckIntBuffer(buf, nord);
buf = IntBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckIntBuffer(buf, nord);
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderLong extends Order {
private static void ckLongBuffer(LongBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
}
static void ckLongBuffer() {
long[] array = new long[LENGTH];
LongBuffer buf = LongBuffer.wrap(array);
ck(buf.order(), nord);
ckLongBuffer(buf, nord);
buf = LongBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckLongBuffer(buf, nord);
buf = LongBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckLongBuffer(buf, nord);
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
/* Type-specific source code for unit test
*
* Regenerate the OrderX classes via genOrder.sh whenever this file changes.
* We check in the generated source files so that the test tree can be used
* independently of the rest of the source tree.
*/
// -- This file was mechanically generated: Do not edit! -- //
import java.nio.*;
public class OrderShort extends Order {
private static void ckShortBuffer(ShortBuffer buf, ByteOrder expected) {
ck(buf.asReadOnlyBuffer().order(), expected);
ck(buf.duplicate().order(), expected);
ck(buf.slice().order(), expected);
}
static void ckShortBuffer() {
short[] array = new short[LENGTH];
ShortBuffer buf = ShortBuffer.wrap(array);
ck(buf.order(), nord);
ckShortBuffer(buf, nord);
buf = ShortBuffer.wrap(array, LENGTH/2, LENGTH/2);
ck(buf.order(), nord);
ckShortBuffer(buf, nord);
buf = ShortBuffer.allocate(LENGTH);
ck(buf.order(), nord);
ckShortBuffer(buf, nord);
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2018, 2026, 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 8208362
* @summary Tests reachability from source to dependent direct byte buffers
* @run junit ReachabilityTest
*/
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.function.UnaryOperator;
import org.junit.jupiter.api.Test;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class ReachabilityTest {
@Test
public void testDuplicate() {
testReachability(ByteBuffer.allocateDirect(16384),
ByteBuffer::duplicate);
}
@Test
public void testSlice() {
testReachability(ByteBuffer.allocateDirect(16384),
ByteBuffer::slice);
}
@Test
public void testViewDuplicate() {
testReachability(ByteBuffer.allocateDirect(16384),
(Buffer b) -> b instanceof ByteBuffer
? ((ByteBuffer) b).asIntBuffer()
: b.duplicate()
);
}
@Test
public void testViewSlice() {
testReachability(ByteBuffer.allocateDirect(16384),
(Buffer b) -> b instanceof ByteBuffer
? ((ByteBuffer) b).asIntBuffer()
: b.slice()
);
}
<T> void testReachability(T t, UnaryOperator<T> b) {
WeakReference<T> root = new WeakReference<>(t);
ReferenceQueue<Object> queue = new ReferenceQueue<>();
List<WeakReference<T>> refs = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
t = b.apply(t);
refs.add(new WeakReference<>(t, queue));
}
t = b.apply(t);
boolean collected = false;
long timeoutMillis = 100L;
try {
for (int tries = 0; tries < 3 && !collected; tries++) {
System.gc();
collected = refs.stream().map(Reference::get).anyMatch(Objects::isNull);
if (!collected) {
collected = queue.remove(timeoutMillis) != null;
timeoutMillis *= 4;
}
}
} catch (InterruptedException unexpected) {
fail("unexpected InterruptedException");
}
// Some or all of the intermediate values must be GC'ed
assertTrue(collected);
// The root should never be GC'ed
assertNotNull(root.get());
Reference.reachabilityFence(t);
}
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2005, 2019, 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 4997655 5071718 7000913
* @summary (bf) CharBuffer.slice() on wrapped CharSequence results in wrong position
*/
import java.nio.CharBuffer;
import java.nio.InvalidMarkException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class StringCharBufferSliceTest {
public static void main( String[] args) throws Exception {
System.out.println(
">>> StringCharBufferSliceTest-main: testing the slice method...");
final String in = "for testing";
System.out.println(
">>> StringCharBufferSliceTest-main: testing with the position 0.");
CharBuffer buff = CharBuffer.wrap(in);
test(buff, buff.slice());
test(buff, buff.slice(0, buff.remaining()));
System.out.println(
">>> StringCharBufferSliceTest-main: testing with new position.");
buff.position(2);
test(buff, buff.slice());
test(buff, buff.slice(2, buff.remaining()));
System.out.println(
">>> StringCharBufferSliceTest-main: testing with non zero initial position.");
buff = CharBuffer.wrap(in, 3, in.length());
test(buff, buff.slice());
test(buff, buff.slice(0, buff.remaining()));
System.out.println(
">>> StringCharBufferSliceTest-main: testing slice result with get()");
buff.position(4);
buff.limit(7);
BiConsumer<CharBuffer,CharBuffer> bitest = (b, s) -> {
for (int i = 0; i < 3; i++) {
if (s.get() != b.get()) {
throw new RuntimeException
("Wrong characters in slice result.");
}
}
};
bitest.accept(buff, buff.slice());
buff.position(4);
bitest.accept(buff, buff.slice(4, 3));
System.out.println(
">>> StringCharBufferSliceTest-main: testing slice result with get(int)");
buff.position(4);
buff.limit(7);
bitest = (b, s) -> {
for (int i = 0; i < 3; i++) {
if (s.get(i) != b.get(4 + i)) {
throw new RuntimeException
("Wrong characters in slice result.");
}
}
};
bitest.accept(buff, buff.slice());
buff.position(4);
bitest.accept(buff, buff.slice(4, 3));
System.out.println(
">>> StringCharBufferSliceTest-main: testing slice with result of slice");
buff.position(0);
buff.limit(buff.capacity());
Consumer<CharBuffer> test = (s) -> {
for (int i=0; i<4; i++) {
s.position(i);
CharBuffer nextSlice = s.slice();
if (nextSlice.position() != 0)
throw new RuntimeException
("New buffer's position should be zero");
if (!nextSlice.equals(s))
throw new RuntimeException("New buffer should be equal");
s = nextSlice;
}
};
test.accept(buff.slice());
test.accept(buff.slice(0, buff.capacity()));
System.out.println(
">>> StringCharBufferSliceTest-main: testing toString.");
buff.position(4);
buff.limit(7);
test = (s) -> {
if (!s.toString().equals("tes")) {
throw new RuntimeException
("bad toString() after slice(): " + s.toString());
}
};
test.accept(buff.slice());
test.accept(buff.slice(4, 3));
System.out.println(
">>> StringCharBufferSliceTest-main: testing subSequence.");
buff.position(4);
buff.limit(8);
test = (s) -> {
CharSequence subSeq = s.subSequence(1, 3);
if (subSeq.charAt(0) != 'e' || subSeq.charAt(1) != 's') {
throw new RuntimeException
("bad subSequence() after slice(): '" + subSeq + "'");
}
};
test.accept(buff.slice());
test.accept(buff.slice(4, 4));
System.out.println(
">>> StringCharBufferSliceTest-main: testing duplicate.");
buff.position(4);
buff.limit(8);
test = (s) -> {
CharBuffer dupe = s.duplicate();
if (dupe.charAt(0) != 't' || dupe.charAt(1) != 'e'
|| dupe.charAt(2) != 's' || dupe.charAt(3) != 't') {
throw new RuntimeException
("bad duplicate() after slice(): '" + dupe + "'");
}
};
test.accept(buff.slice());
test.accept(buff.slice(4, 4));
System.out.println(">>> StringCharBufferSliceTest-main: done!");
}
public static void test(CharBuffer buff, CharBuffer slice) throws RuntimeException {
boolean marked = false;
try {
slice.reset();
marked = true;
} catch (InvalidMarkException ime) {
// expected
}
if (marked ||
slice.position() != 0 ||
buff.remaining() != slice.limit() ||
buff.remaining() != slice.capacity()) {
throw new RuntimeException(
"Calling the CharBuffer.slice method failed.");
}
}
}

View file

@ -0,0 +1,246 @@
/*
* Copyright (c) 2007, 2016, 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.
*/
/*
* This is not a regression test, but a micro-benchmark.
* To exercise swap, run with filter=LITTLE_ENDIAN on sparc,
* filter=BIG_ENDIAN on x86.
*
* I have run this as follows:
*
* for f in -client -server; do mergeBench dolphin . jr -dsa -da $f SwapMicroBenchmark.java filter=LITTLE_ENDIAN; done
*
* @author Martin Buchholz
*/
import java.util.*;
import java.nio.*;
import java.util.regex.Pattern;
public class SwapMicroBenchmark {
abstract static class Job {
private final String name;
public Job(String name) { this.name = name; }
public String name() { return name; }
public abstract void work() throws Throwable;
}
private static void collectAllGarbage() {
final java.util.concurrent.CountDownLatch drained
= new java.util.concurrent.CountDownLatch(1);
try {
System.gc(); // enqueue finalizable objects
new Object() { protected void finalize() {
drained.countDown(); }};
System.gc(); // enqueue detector
drained.await(); // wait for finalizer queue to drain
System.gc(); // cleanup finalized objects
} catch (InterruptedException e) { throw new Error(e); }
}
/**
* Runs each job for long enough that all the runtime compilers
* have had plenty of time to warm up, i.e. get around to
* compiling everything worth compiling.
* Returns array of average times per job per run.
*/
private static long[] time0(Job ... jobs) throws Throwable {
final long warmupNanos = 10L * 1000L * 1000L * 1000L;
long[] nanoss = new long[jobs.length];
for (int i = 0; i < jobs.length; i++) {
collectAllGarbage();
long t0 = System.nanoTime();
long t;
int j = 0;
do { jobs[i].work(); j++; }
while ((t = System.nanoTime() - t0) < warmupNanos);
nanoss[i] = t/j;
}
return nanoss;
}
private static void time(Job ... jobs) throws Throwable {
long[] warmup = time0(jobs); // Warm up run
long[] nanoss = time0(jobs); // Real timing run
long[] milliss = new long[jobs.length];
double[] ratios = new double[jobs.length];
final String nameHeader = "Method";
final String millisHeader = "Millis";
final String ratioHeader = "Ratio";
int nameWidth = nameHeader.length();
int millisWidth = millisHeader.length();
int ratioWidth = ratioHeader.length();
for (int i = 0; i < jobs.length; i++) {
nameWidth = Math.max(nameWidth, jobs[i].name().length());
milliss[i] = nanoss[i]/(1000L * 1000L);
millisWidth = Math.max(millisWidth,
String.format("%d", milliss[i]).length());
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
ratioWidth = Math.max(ratioWidth,
String.format("%.3f", ratios[i]).length());
}
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
nameWidth, millisWidth, ratioWidth);
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
nameWidth, millisWidth, ratioWidth);
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
// Print out absolute and relative times, calibrated against first job
for (int i = 0; i < jobs.length; i++)
System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);
}
private static String keywordValue(String[] args, String keyword) {
for (String arg : args)
if (arg.startsWith(keyword))
return arg.substring(keyword.length() + 1);
return null;
}
private static int intArg(String[] args, String keyword, int defaultValue) {
String val = keywordValue(args, keyword);
return val == null ? defaultValue : Integer.parseInt(val);
}
private static Pattern patternArg(String[] args, String keyword) {
String val = keywordValue(args, keyword);
return val == null ? null : Pattern.compile(val);
}
private static Job[] filter(Pattern filter, Job[] jobs) {
if (filter == null) return jobs;
Job[] newJobs = new Job[jobs.length];
int n = 0;
for (Job job : jobs)
if (filter.matcher(job.name()).find())
newJobs[n++] = job;
// Arrays.copyOf not available in JDK 5
Job[] ret = new Job[n];
System.arraycopy(newJobs, 0, ret, 0, n);
return ret;
}
private static void deoptimize(int sum) {
if (sum == 42)
System.out.println("the answer");
}
/**
* Usage: [iterations=N] [size=N] [filter=REGEXP]
*/
public static void main(String[] args) throws Throwable {
final int iterations = intArg(args, "iterations", 10000);
final int size = intArg(args, "size", 1024);
final Pattern filter = patternArg(args, "filter");
final Random rnd = new Random();
final ByteBuffer b = ByteBuffer.allocateDirect(8*size);
for (int i = 0; i < b.limit(); i++)
b.put(i, (byte) rnd.nextInt());
Job[] jobs = {
new Job("swap char BIG_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.BIG_ENDIAN);
CharBuffer x = b.asCharBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap char LITTLE_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.LITTLE_ENDIAN);
CharBuffer x = b.asCharBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap short BIG_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.BIG_ENDIAN);
ShortBuffer x = b.asShortBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap short LITTLE_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer x = b.asShortBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap int BIG_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.BIG_ENDIAN);
IntBuffer x = b.asIntBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap int LITTLE_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.LITTLE_ENDIAN);
IntBuffer x = b.asIntBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap long BIG_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.BIG_ENDIAN);
LongBuffer x = b.asLongBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}},
new Job("swap long LITTLE_ENDIAN") {
public void work() throws Throwable {
b.order(ByteOrder.LITTLE_ENDIAN);
LongBuffer x = b.asLongBuffer();
for (int i = 0; i < iterations; i++) {
int sum = 0;
for (int j = 0, end = x.limit(); j < end; j++)
sum += x.get(j);
deoptimize(sum);}}}
};
time(filter(filter, jobs));
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2024, 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 8344882
* @summary Deallocation failure for temporary buffers
* @run junit/othervm -XX:MaxDirectMemorySize=32768 UnmeteredTempBuffers
*/
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import static java.nio.file.StandardOpenOption.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*;
public class UnmeteredTempBuffers {
@ParameterizedTest
@ValueSource(ints = {16384, 32768, 32769, 65536})
void testFileChannel(int cap) throws IOException {
Path file = Files.createTempFile("prefix", "suffix");
try (FileChannel ch = FileChannel.open(file, WRITE, DELETE_ON_CLOSE)) {
ByteBuffer buf = ByteBuffer.wrap(new byte[cap]);
try {
ch.write(buf);
} catch (OutOfMemoryError oome) {
throw new RuntimeException(oome);
}
} finally {
Files.deleteIfExists(file);
}
}
@ParameterizedTest
@ValueSource(ints = {16384, 32768, 32769, 65536})
void testInputStream(int cap) throws IOException {
Path file = Files.createTempFile("prefix", "suffix");
try {
byte[] bytes = new byte[cap];
Files.write(file, bytes);
try (InputStream in = Files.newInputStream(file)) {
in.read(bytes);
} catch (OutOfMemoryError oome) {
throw new RuntimeException(oome);
}
} finally {
Files.delete(file);
}
}
}

View file

@ -0,0 +1,40 @@
#! /bin/sh
#
# Copyright (c) 2000, 2019, 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.
#
javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java
gen() {
out=Basic$2.java
rm -f $out
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 -iBasic-X.java.template -o$out
}
gen byte Byte Byte
gen char Char Character
gen short Short Short
gen int Int Integer
gen long Long Long
gen float Float Float
gen double Double Double

View file

@ -0,0 +1,42 @@
#! /bin/sh
#
# Copyright (c) 2002, 2019, 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.
#
javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java
gen() {
out=CopyDirect$2Memory.java
rm -f $out
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 -iCopyDirect-X-Memory.java.template -o$out
}
gen byte Byte Byte
gen char Char Character
gen short Short Short
gen int Int Integer
gen long Long Long
gen float Float Float
gen double Double Double
rm -rf build

View file

@ -0,0 +1,40 @@
#! /bin/sh
#
# Copyright (c) 2002, 2019, 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.
#
javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java
gen() {
out=Order$2.java
rm -f $out
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 -iOrder-X.java.template -o$out
}
gen char Char Character
gen short Short Short
gen int Int Integer
gen long Long Long
gen float Float Float
gen double Double Double
rm -rf build