8300236: Use VarHandle access in Data(Input | Output)Stream classes
Reviewed-by: rriggs, alanb
This commit is contained in:
parent
a5d8e12872
commit
74e1a8bfa8
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.io;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.VarHandle;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for packing/unpacking primitive values in/out of byte arrays
|
|
||||||
* using big-endian byte ordering (i.e. "Network Order").
|
|
||||||
*/
|
|
||||||
final class Bits {
|
|
||||||
private Bits() {}
|
|
||||||
|
|
||||||
private static final VarHandle SHORT = create(short[].class);
|
|
||||||
private static final VarHandle INT = create(int[].class);
|
|
||||||
private static final VarHandle LONG = create(long[].class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Methods for unpacking primitive values from byte arrays starting at
|
|
||||||
* given offsets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static boolean getBoolean(byte[] b, int off) {
|
|
||||||
return b[off] != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char getChar(byte[] b, int off) {
|
|
||||||
return (char) (short) SHORT.get(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static short getShort(byte[] b, int off) {
|
|
||||||
return (short) SHORT.get(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getInt(byte[] b, int off) {
|
|
||||||
return (int) INT.get(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float getFloat(byte[] b, int off) {
|
|
||||||
// Using Float.intBitsToFloat collapses NaN values to a single
|
|
||||||
// "canonical" NaN value
|
|
||||||
return Float.intBitsToFloat((int) INT.get(b, off));
|
|
||||||
}
|
|
||||||
|
|
||||||
static long getLong(byte[] b, int off) {
|
|
||||||
return (long) LONG.get(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double getDouble(byte[] b, int off) {
|
|
||||||
// Using Double.longBitsToDouble collapses NaN values to a single
|
|
||||||
// "canonical" NaN value
|
|
||||||
return Double.longBitsToDouble((long) LONG.get(b, off));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Methods for packing primitive values into byte arrays starting at given
|
|
||||||
* offsets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void putBoolean(byte[] b, int off, boolean val) {
|
|
||||||
b[off] = (byte) (val ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putChar(byte[] b, int off, char val) {
|
|
||||||
SHORT.set(b, off, (short) val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putShort(byte[] b, int off, short val) {
|
|
||||||
SHORT.set(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putInt(byte[] b, int off, int val) {
|
|
||||||
INT.set(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putFloat(byte[] b, int off, float val) {
|
|
||||||
// Using Float.floatToIntBits collapses NaN values to a single
|
|
||||||
// "canonical" NaN value
|
|
||||||
INT.set(b, off, Float.floatToIntBits(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putLong(byte[] b, int off, long val) {
|
|
||||||
LONG.set(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void putDouble(byte[] b, int off, double val) {
|
|
||||||
// Using Double.doubleToLongBits collapses NaN values to a single
|
|
||||||
// "canonical" NaN value
|
|
||||||
LONG.set(b, off, Double.doubleToLongBits(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static VarHandle create(Class<?> viewArrayClass) {
|
|
||||||
return MethodHandles.byteArrayViewVarHandle(viewArrayClass, ByteOrder.BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,6 +56,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
super(in);
|
super(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final byte[] readBuffer = new byte[8];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* working arrays initialized on demand by readUTF
|
* working arrays initialized on demand by readUTF
|
||||||
*/
|
*/
|
||||||
@ -309,7 +313,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public final short readShort() throws IOException {
|
public final short readShort() throws IOException {
|
||||||
return (short) readUnsignedShort();
|
readFully(readBuffer, 0, 2);
|
||||||
|
return ByteArray.getShort(readBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -330,12 +335,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public final int readUnsignedShort() throws IOException {
|
public final int readUnsignedShort() throws IOException {
|
||||||
InputStream in = this.in;
|
readFully(readBuffer, 0, 2);
|
||||||
int ch1 = in.read();
|
return ByteArray.getUnsignedShort(readBuffer, 0);
|
||||||
int ch2 = in.read();
|
|
||||||
if ((ch1 | ch2) < 0)
|
|
||||||
throw new EOFException();
|
|
||||||
return (ch1 << 8) + (ch2 << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -356,7 +357,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public final char readChar() throws IOException {
|
public final char readChar() throws IOException {
|
||||||
return (char) readUnsignedShort();
|
readFully(readBuffer, 0, 2);
|
||||||
|
return ByteArray.getChar(readBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,18 +379,10 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public final int readInt() throws IOException {
|
public final int readInt() throws IOException {
|
||||||
InputStream in = this.in;
|
readFully(readBuffer, 0, 4);
|
||||||
int ch1 = in.read();
|
return ByteArray.getInt(readBuffer, 0);
|
||||||
int ch2 = in.read();
|
|
||||||
int ch3 = in.read();
|
|
||||||
int ch4 = in.read();
|
|
||||||
if ((ch1 | ch2 | ch3 | ch4) < 0)
|
|
||||||
throw new EOFException();
|
|
||||||
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final byte[] readBuffer = new byte[8];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See the general contract of the {@code readLong}
|
* See the general contract of the {@code readLong}
|
||||||
* method of {@code DataInput}.
|
* method of {@code DataInput}.
|
||||||
@ -408,14 +402,7 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
*/
|
*/
|
||||||
public final long readLong() throws IOException {
|
public final long readLong() throws IOException {
|
||||||
readFully(readBuffer, 0, 8);
|
readFully(readBuffer, 0, 8);
|
||||||
return (((long)readBuffer[0] << 56) +
|
return ByteArray.getLong(readBuffer, 0);
|
||||||
((long)(readBuffer[1] & 255) << 48) +
|
|
||||||
((long)(readBuffer[2] & 255) << 40) +
|
|
||||||
((long)(readBuffer[3] & 255) << 32) +
|
|
||||||
((long)(readBuffer[4] & 255) << 24) +
|
|
||||||
((readBuffer[5] & 255) << 16) +
|
|
||||||
((readBuffer[6] & 255) << 8) +
|
|
||||||
((readBuffer[7] & 255) << 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -437,7 +424,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.lang.Float#intBitsToFloat(int)
|
* @see java.lang.Float#intBitsToFloat(int)
|
||||||
*/
|
*/
|
||||||
public final float readFloat() throws IOException {
|
public final float readFloat() throws IOException {
|
||||||
return Float.intBitsToFloat(readInt());
|
readFully(readBuffer, 0, 4);
|
||||||
|
return ByteArray.getFloat(readBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,7 +447,8 @@ public class DataInputStream extends FilterInputStream implements DataInput {
|
|||||||
* @see java.lang.Double#longBitsToDouble(long)
|
* @see java.lang.Double#longBitsToDouble(long)
|
||||||
*/
|
*/
|
||||||
public final double readDouble() throws IOException {
|
public final double readDouble() throws IOException {
|
||||||
return Double.longBitsToDouble(readLong());
|
readFully(readBuffer, 0, 8);
|
||||||
|
return ByteArray.getDouble(readBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] lineBuffer;
|
private char[] lineBuffer;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data output stream lets an application write primitive Java data
|
* A data output stream lets an application write primitive Java data
|
||||||
* types to an output stream in a portable way. An application can
|
* types to an output stream in a portable way. An application can
|
||||||
@ -170,8 +172,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.io.FilterOutputStream#out
|
* @see java.io.FilterOutputStream#out
|
||||||
*/
|
*/
|
||||||
public final void writeShort(int v) throws IOException {
|
public final void writeShort(int v) throws IOException {
|
||||||
writeBuffer[0] = (byte)(v >>> 8);
|
ByteArray.setUnsignedShort(writeBuffer, 0, v);
|
||||||
writeBuffer[1] = (byte)(v >>> 0);
|
|
||||||
out.write(writeBuffer, 0, 2);
|
out.write(writeBuffer, 0, 2);
|
||||||
incCount(2);
|
incCount(2);
|
||||||
}
|
}
|
||||||
@ -186,8 +187,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.io.FilterOutputStream#out
|
* @see java.io.FilterOutputStream#out
|
||||||
*/
|
*/
|
||||||
public final void writeChar(int v) throws IOException {
|
public final void writeChar(int v) throws IOException {
|
||||||
writeBuffer[0] = (byte)(v >>> 8);
|
ByteArray.setUnsignedShort(writeBuffer, 0, v);
|
||||||
writeBuffer[1] = (byte)(v >>> 0);
|
|
||||||
out.write(writeBuffer, 0, 2);
|
out.write(writeBuffer, 0, 2);
|
||||||
incCount(2);
|
incCount(2);
|
||||||
}
|
}
|
||||||
@ -202,10 +202,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.io.FilterOutputStream#out
|
* @see java.io.FilterOutputStream#out
|
||||||
*/
|
*/
|
||||||
public final void writeInt(int v) throws IOException {
|
public final void writeInt(int v) throws IOException {
|
||||||
writeBuffer[0] = (byte)(v >>> 24);
|
ByteArray.setInt(writeBuffer, 0, v);
|
||||||
writeBuffer[1] = (byte)(v >>> 16);
|
|
||||||
writeBuffer[2] = (byte)(v >>> 8);
|
|
||||||
writeBuffer[3] = (byte)(v >>> 0);
|
|
||||||
out.write(writeBuffer, 0, 4);
|
out.write(writeBuffer, 0, 4);
|
||||||
incCount(4);
|
incCount(4);
|
||||||
}
|
}
|
||||||
@ -220,14 +217,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.io.FilterOutputStream#out
|
* @see java.io.FilterOutputStream#out
|
||||||
*/
|
*/
|
||||||
public final void writeLong(long v) throws IOException {
|
public final void writeLong(long v) throws IOException {
|
||||||
writeBuffer[0] = (byte)(v >>> 56);
|
ByteArray.setLong(writeBuffer, 0, v);
|
||||||
writeBuffer[1] = (byte)(v >>> 48);
|
|
||||||
writeBuffer[2] = (byte)(v >>> 40);
|
|
||||||
writeBuffer[3] = (byte)(v >>> 32);
|
|
||||||
writeBuffer[4] = (byte)(v >>> 24);
|
|
||||||
writeBuffer[5] = (byte)(v >>> 16);
|
|
||||||
writeBuffer[6] = (byte)(v >>> 8);
|
|
||||||
writeBuffer[7] = (byte)(v >>> 0);
|
|
||||||
out.write(writeBuffer, 0, 8);
|
out.write(writeBuffer, 0, 8);
|
||||||
incCount(8);
|
incCount(8);
|
||||||
}
|
}
|
||||||
@ -246,7 +236,9 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.lang.Float#floatToIntBits(float)
|
* @see java.lang.Float#floatToIntBits(float)
|
||||||
*/
|
*/
|
||||||
public final void writeFloat(float v) throws IOException {
|
public final void writeFloat(float v) throws IOException {
|
||||||
writeInt(Float.floatToIntBits(v));
|
ByteArray.setFloat(writeBuffer, 0, v);
|
||||||
|
out.write(writeBuffer, 0, 4);
|
||||||
|
incCount(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,7 +255,9 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
* @see java.lang.Double#doubleToLongBits(double)
|
* @see java.lang.Double#doubleToLongBits(double)
|
||||||
*/
|
*/
|
||||||
public final void writeDouble(double v) throws IOException {
|
public final void writeDouble(double v) throws IOException {
|
||||||
writeLong(Double.doubleToLongBits(v));
|
ByteArray.setDouble(writeBuffer, 0, v);
|
||||||
|
out.write(writeBuffer, 0, 8);
|
||||||
|
incCount(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,8 +295,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
int len = s.length();
|
int len = s.length();
|
||||||
for (int i = 0 ; i < len ; i++) {
|
for (int i = 0 ; i < len ; i++) {
|
||||||
int v = s.charAt(i);
|
int v = s.charAt(i);
|
||||||
writeBuffer[0] = (byte)(v >>> 8);
|
ByteArray.setUnsignedShort(writeBuffer, 0, v);
|
||||||
writeBuffer[1] = (byte)(v >>> 0);
|
|
||||||
out.write(writeBuffer, 0, 2);
|
out.write(writeBuffer, 0, 2);
|
||||||
}
|
}
|
||||||
incCount(len * 2);
|
incCount(len * 2);
|
||||||
@ -379,9 +372,8 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
|
ByteArray.setUnsignedShort(bytearr, count, utflen);
|
||||||
bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
|
count += 2;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0; i < strlen; i++) { // optimized for initial run of ASCII
|
for (i = 0; i < strlen; i++) { // optimized for initial run of ASCII
|
||||||
int c = str.charAt(i);
|
int c = str.charAt(i);
|
||||||
|
@ -45,6 +45,7 @@ import java.util.Objects;
|
|||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.event.DeserializationEvent;
|
import jdk.internal.event.DeserializationEvent;
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
import sun.security.action.GetBooleanAction;
|
import sun.security.action.GetBooleanAction;
|
||||||
import sun.security.action.GetIntegerAction;
|
import sun.security.action.GetIntegerAction;
|
||||||
@ -2631,7 +2632,7 @@ public class ObjectInputStream
|
|||||||
|
|
||||||
public boolean get(String name, boolean val) {
|
public boolean get(String name, boolean val) {
|
||||||
int off = getFieldOffset(name, Boolean.TYPE);
|
int off = getFieldOffset(name, Boolean.TYPE);
|
||||||
return (off >= 0) ? Bits.getBoolean(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getBoolean(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte get(String name, byte val) {
|
public byte get(String name, byte val) {
|
||||||
@ -2641,32 +2642,32 @@ public class ObjectInputStream
|
|||||||
|
|
||||||
public char get(String name, char val) {
|
public char get(String name, char val) {
|
||||||
int off = getFieldOffset(name, Character.TYPE);
|
int off = getFieldOffset(name, Character.TYPE);
|
||||||
return (off >= 0) ? Bits.getChar(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getChar(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short get(String name, short val) {
|
public short get(String name, short val) {
|
||||||
int off = getFieldOffset(name, Short.TYPE);
|
int off = getFieldOffset(name, Short.TYPE);
|
||||||
return (off >= 0) ? Bits.getShort(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getShort(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int get(String name, int val) {
|
public int get(String name, int val) {
|
||||||
int off = getFieldOffset(name, Integer.TYPE);
|
int off = getFieldOffset(name, Integer.TYPE);
|
||||||
return (off >= 0) ? Bits.getInt(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getInt(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float get(String name, float val) {
|
public float get(String name, float val) {
|
||||||
int off = getFieldOffset(name, Float.TYPE);
|
int off = getFieldOffset(name, Float.TYPE);
|
||||||
return (off >= 0) ? Bits.getFloat(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getFloat(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long get(String name, long val) {
|
public long get(String name, long val) {
|
||||||
int off = getFieldOffset(name, Long.TYPE);
|
int off = getFieldOffset(name, Long.TYPE);
|
||||||
return (off >= 0) ? Bits.getLong(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getLong(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double get(String name, double val) {
|
public double get(String name, double val) {
|
||||||
int off = getFieldOffset(name, Double.TYPE);
|
int off = getFieldOffset(name, Double.TYPE);
|
||||||
return (off >= 0) ? Bits.getDouble(primValues, off) : val;
|
return (off >= 0) ? ByteArray.getDouble(primValues, off) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(String name, Object val) throws ClassNotFoundException {
|
public Object get(String name, Object val) throws ClassNotFoundException {
|
||||||
@ -3114,7 +3115,7 @@ public class ObjectInputStream
|
|||||||
return HEADER_BLOCKED;
|
return HEADER_BLOCKED;
|
||||||
}
|
}
|
||||||
in.readFully(hbuf, 0, 5);
|
in.readFully(hbuf, 0, 5);
|
||||||
int len = Bits.getInt(hbuf, 1);
|
int len = ByteArray.getInt(hbuf, 1);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
throw new StreamCorruptedException(
|
throw new StreamCorruptedException(
|
||||||
"illegal block data header length: " +
|
"illegal block data header length: " +
|
||||||
@ -3413,7 +3414,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 2) {
|
} else if (end - pos < 2) {
|
||||||
return din.readChar();
|
return din.readChar();
|
||||||
}
|
}
|
||||||
char v = Bits.getChar(buf, pos);
|
char v = ByteArray.getChar(buf, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3425,7 +3426,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 2) {
|
} else if (end - pos < 2) {
|
||||||
return din.readShort();
|
return din.readShort();
|
||||||
}
|
}
|
||||||
short v = Bits.getShort(buf, pos);
|
short v = ByteArray.getShort(buf, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3437,7 +3438,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 2) {
|
} else if (end - pos < 2) {
|
||||||
return din.readUnsignedShort();
|
return din.readUnsignedShort();
|
||||||
}
|
}
|
||||||
int v = Bits.getShort(buf, pos) & 0xFFFF;
|
int v = ByteArray.getShort(buf, pos) & 0xFFFF;
|
||||||
pos += 2;
|
pos += 2;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3449,7 +3450,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 4) {
|
} else if (end - pos < 4) {
|
||||||
return din.readInt();
|
return din.readInt();
|
||||||
}
|
}
|
||||||
int v = Bits.getInt(buf, pos);
|
int v = ByteArray.getInt(buf, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3461,7 +3462,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 4) {
|
} else if (end - pos < 4) {
|
||||||
return din.readFloat();
|
return din.readFloat();
|
||||||
}
|
}
|
||||||
float v = Bits.getFloat(buf, pos);
|
float v = ByteArray.getFloat(buf, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3473,7 +3474,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 8) {
|
} else if (end - pos < 8) {
|
||||||
return din.readLong();
|
return din.readLong();
|
||||||
}
|
}
|
||||||
long v = Bits.getLong(buf, pos);
|
long v = ByteArray.getLong(buf, pos);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3485,7 +3486,7 @@ public class ObjectInputStream
|
|||||||
} else if (end - pos < 8) {
|
} else if (end - pos < 8) {
|
||||||
return din.readDouble();
|
return din.readDouble();
|
||||||
}
|
}
|
||||||
double v = Bits.getDouble(buf, pos);
|
double v = ByteArray.getDouble(buf, pos);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -3523,7 +3524,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getBoolean(buf, pos++);
|
v[off++] = ByteArray.getBoolean(buf, pos++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3544,7 +3545,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getChar(buf, pos);
|
v[off++] = ByteArray.getChar(buf, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3566,7 +3567,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getShort(buf, pos);
|
v[off++] = ByteArray.getShort(buf, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3588,7 +3589,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getInt(buf, pos);
|
v[off++] = ByteArray.getInt(buf, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3610,7 +3611,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getFloat(buf, pos);
|
v[off++] = ByteArray.getFloat(buf, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3632,7 +3633,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getLong(buf, pos);
|
v[off++] = ByteArray.getLong(buf, pos);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3654,7 +3655,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
v[off++] = Bits.getDouble(buf, pos);
|
v[off++] = ByteArray.getDouble(buf, pos);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1638,7 +1640,7 @@ public class ObjectOutputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, boolean val) {
|
public void put(String name, boolean val) {
|
||||||
Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
|
ByteArray.setBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, byte val) {
|
public void put(String name, byte val) {
|
||||||
@ -1646,27 +1648,27 @@ public class ObjectOutputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, char val) {
|
public void put(String name, char val) {
|
||||||
Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
|
ByteArray.setChar(primVals, getFieldOffset(name, Character.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, short val) {
|
public void put(String name, short val) {
|
||||||
Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
|
ByteArray.setShort(primVals, getFieldOffset(name, Short.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, int val) {
|
public void put(String name, int val) {
|
||||||
Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
|
ByteArray.setInt(primVals, getFieldOffset(name, Integer.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, float val) {
|
public void put(String name, float val) {
|
||||||
Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
|
ByteArray.setFloat(primVals, getFieldOffset(name, Float.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, long val) {
|
public void put(String name, long val) {
|
||||||
Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
|
ByteArray.setLong(primVals, getFieldOffset(name, Long.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, double val) {
|
public void put(String name, double val) {
|
||||||
Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
|
ByteArray.setDouble(primVals, getFieldOffset(name, Double.TYPE), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, Object val) {
|
public void put(String name, Object val) {
|
||||||
@ -1908,7 +1910,7 @@ public class ObjectOutputStream
|
|||||||
out.write(hbuf, 0, 2);
|
out.write(hbuf, 0, 2);
|
||||||
} else {
|
} else {
|
||||||
hbuf[0] = TC_BLOCKDATALONG;
|
hbuf[0] = TC_BLOCKDATALONG;
|
||||||
Bits.putInt(hbuf, 1, len);
|
ByteArray.setInt(hbuf, 1, len);
|
||||||
out.write(hbuf, 0, 5);
|
out.write(hbuf, 0, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1925,7 +1927,7 @@ public class ObjectOutputStream
|
|||||||
if (pos >= MAX_BLOCK_SIZE) {
|
if (pos >= MAX_BLOCK_SIZE) {
|
||||||
drain();
|
drain();
|
||||||
}
|
}
|
||||||
Bits.putBoolean(buf, pos++, v);
|
ByteArray.setBoolean(buf, pos++, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeByte(int v) throws IOException {
|
public void writeByte(int v) throws IOException {
|
||||||
@ -1937,7 +1939,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeChar(int v) throws IOException {
|
public void writeChar(int v) throws IOException {
|
||||||
if (pos + 2 <= MAX_BLOCK_SIZE) {
|
if (pos + 2 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putChar(buf, pos, (char) v);
|
ByteArray.setChar(buf, pos, (char) v);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
} else {
|
} else {
|
||||||
dout.writeChar(v);
|
dout.writeChar(v);
|
||||||
@ -1946,7 +1948,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeShort(int v) throws IOException {
|
public void writeShort(int v) throws IOException {
|
||||||
if (pos + 2 <= MAX_BLOCK_SIZE) {
|
if (pos + 2 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putShort(buf, pos, (short) v);
|
ByteArray.setShort(buf, pos, (short) v);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
} else {
|
} else {
|
||||||
dout.writeShort(v);
|
dout.writeShort(v);
|
||||||
@ -1955,7 +1957,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeInt(int v) throws IOException {
|
public void writeInt(int v) throws IOException {
|
||||||
if (pos + 4 <= MAX_BLOCK_SIZE) {
|
if (pos + 4 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putInt(buf, pos, v);
|
ByteArray.setInt(buf, pos, v);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
} else {
|
} else {
|
||||||
dout.writeInt(v);
|
dout.writeInt(v);
|
||||||
@ -1964,7 +1966,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeFloat(float v) throws IOException {
|
public void writeFloat(float v) throws IOException {
|
||||||
if (pos + 4 <= MAX_BLOCK_SIZE) {
|
if (pos + 4 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putFloat(buf, pos, v);
|
ByteArray.setFloat(buf, pos, v);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
} else {
|
} else {
|
||||||
dout.writeFloat(v);
|
dout.writeFloat(v);
|
||||||
@ -1973,7 +1975,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeLong(long v) throws IOException {
|
public void writeLong(long v) throws IOException {
|
||||||
if (pos + 8 <= MAX_BLOCK_SIZE) {
|
if (pos + 8 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putLong(buf, pos, v);
|
ByteArray.setLong(buf, pos, v);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
} else {
|
} else {
|
||||||
dout.writeLong(v);
|
dout.writeLong(v);
|
||||||
@ -1982,7 +1984,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
public void writeDouble(double v) throws IOException {
|
public void writeDouble(double v) throws IOException {
|
||||||
if (pos + 8 <= MAX_BLOCK_SIZE) {
|
if (pos + 8 <= MAX_BLOCK_SIZE) {
|
||||||
Bits.putDouble(buf, pos, v);
|
ByteArray.setDouble(buf, pos, v);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
} else {
|
} else {
|
||||||
dout.writeDouble(v);
|
dout.writeDouble(v);
|
||||||
@ -2042,7 +2044,7 @@ public class ObjectOutputStream
|
|||||||
}
|
}
|
||||||
int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
|
int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putBoolean(buf, pos++, v[off++]);
|
ByteArray.setBoolean(buf, pos++, v[off++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2055,7 +2057,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 1;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 1;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putChar(buf, pos, v[off++]);
|
ByteArray.setChar(buf, pos, v[off++]);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2072,7 +2074,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 1;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 1;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putShort(buf, pos, v[off++]);
|
ByteArray.setShort(buf, pos, v[off++]);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2089,7 +2091,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 2;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 2;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putInt(buf, pos, v[off++]);
|
ByteArray.setInt(buf, pos, v[off++]);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2106,7 +2108,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 2;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 2;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putFloat(buf, pos, v[off++]);
|
ByteArray.setFloat(buf, pos, v[off++]);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2123,7 +2125,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 3;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 3;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putLong(buf, pos, v[off++]);
|
ByteArray.setLong(buf, pos, v[off++]);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2140,7 +2142,7 @@ public class ObjectOutputStream
|
|||||||
int avail = (MAX_BLOCK_SIZE - pos) >> 3;
|
int avail = (MAX_BLOCK_SIZE - pos) >> 3;
|
||||||
int stop = Math.min(endoff, off + avail);
|
int stop = Math.min(endoff, off + avail);
|
||||||
while (off < stop) {
|
while (off < stop) {
|
||||||
Bits.putDouble(buf, pos, v[off++]);
|
ByteArray.setDouble(buf, pos, v[off++]);
|
||||||
pos += 8;
|
pos += 8;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,6 +61,7 @@ import jdk.internal.reflect.Reflection;
|
|||||||
import jdk.internal.reflect.ReflectionFactory;
|
import jdk.internal.reflect.ReflectionFactory;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.access.JavaSecurityAccess;
|
import jdk.internal.access.JavaSecurityAccess;
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1986,14 +1987,14 @@ public final class ObjectStreamClass implements Serializable {
|
|||||||
long key = readKeys[i];
|
long key = readKeys[i];
|
||||||
int off = offsets[i];
|
int off = offsets[i];
|
||||||
switch (typeCodes[i]) {
|
switch (typeCodes[i]) {
|
||||||
case 'Z' -> Bits.putBoolean(buf, off, UNSAFE.getBoolean(obj, key));
|
case 'Z' -> ByteArray.setBoolean(buf, off, UNSAFE.getBoolean(obj, key));
|
||||||
case 'B' -> buf[off] = UNSAFE.getByte(obj, key);
|
case 'B' -> buf[off] = UNSAFE.getByte(obj, key);
|
||||||
case 'C' -> Bits.putChar(buf, off, UNSAFE.getChar(obj, key));
|
case 'C' -> ByteArray.setChar(buf, off, UNSAFE.getChar(obj, key));
|
||||||
case 'S' -> Bits.putShort(buf, off, UNSAFE.getShort(obj, key));
|
case 'S' -> ByteArray.setShort(buf, off, UNSAFE.getShort(obj, key));
|
||||||
case 'I' -> Bits.putInt(buf, off, UNSAFE.getInt(obj, key));
|
case 'I' -> ByteArray.setInt(buf, off, UNSAFE.getInt(obj, key));
|
||||||
case 'F' -> Bits.putFloat(buf, off, UNSAFE.getFloat(obj, key));
|
case 'F' -> ByteArray.setFloat(buf, off, UNSAFE.getFloat(obj, key));
|
||||||
case 'J' -> Bits.putLong(buf, off, UNSAFE.getLong(obj, key));
|
case 'J' -> ByteArray.setLong(buf, off, UNSAFE.getLong(obj, key));
|
||||||
case 'D' -> Bits.putDouble(buf, off, UNSAFE.getDouble(obj, key));
|
case 'D' -> ByteArray.setDouble(buf, off, UNSAFE.getDouble(obj, key));
|
||||||
default -> throw new InternalError();
|
default -> throw new InternalError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2015,14 +2016,14 @@ public final class ObjectStreamClass implements Serializable {
|
|||||||
}
|
}
|
||||||
int off = offsets[i];
|
int off = offsets[i];
|
||||||
switch (typeCodes[i]) {
|
switch (typeCodes[i]) {
|
||||||
case 'Z' -> UNSAFE.putBoolean(obj, key, Bits.getBoolean(buf, off));
|
case 'Z' -> UNSAFE.putBoolean(obj, key, ByteArray.getBoolean(buf, off));
|
||||||
case 'B' -> UNSAFE.putByte(obj, key, buf[off]);
|
case 'B' -> UNSAFE.putByte(obj, key, buf[off]);
|
||||||
case 'C' -> UNSAFE.putChar(obj, key, Bits.getChar(buf, off));
|
case 'C' -> UNSAFE.putChar(obj, key, ByteArray.getChar(buf, off));
|
||||||
case 'S' -> UNSAFE.putShort(obj, key, Bits.getShort(buf, off));
|
case 'S' -> UNSAFE.putShort(obj, key, ByteArray.getShort(buf, off));
|
||||||
case 'I' -> UNSAFE.putInt(obj, key, Bits.getInt(buf, off));
|
case 'I' -> UNSAFE.putInt(obj, key, ByteArray.getInt(buf, off));
|
||||||
case 'F' -> UNSAFE.putFloat(obj, key, Bits.getFloat(buf, off));
|
case 'F' -> UNSAFE.putFloat(obj, key, ByteArray.getFloat(buf, off));
|
||||||
case 'J' -> UNSAFE.putLong(obj, key, Bits.getLong(buf, off));
|
case 'J' -> UNSAFE.putLong(obj, key, ByteArray.getLong(buf, off));
|
||||||
case 'D' -> UNSAFE.putDouble(obj, key, Bits.getDouble(buf, off));
|
case 'D' -> UNSAFE.putDouble(obj, key, ByteArray.getDouble(buf, off));
|
||||||
default -> throw new InternalError();
|
default -> throw new InternalError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2473,16 +2474,16 @@ public final class ObjectStreamClass implements Serializable {
|
|||||||
try {
|
try {
|
||||||
PRIM_VALUE_EXTRACTORS = Map.of(
|
PRIM_VALUE_EXTRACTORS = Map.of(
|
||||||
byte.class, MethodHandles.arrayElementGetter(byte[].class),
|
byte.class, MethodHandles.arrayElementGetter(byte[].class),
|
||||||
short.class, lkp.findStatic(Bits.class, "getShort", MethodType.methodType(short.class, byte[].class, int.class)),
|
short.class, lkp.findStatic(ByteArray.class, "getShort", MethodType.methodType(short.class, byte[].class, int.class)),
|
||||||
int.class, lkp.findStatic(Bits.class, "getInt", MethodType.methodType(int.class, byte[].class, int.class)),
|
int.class, lkp.findStatic(ByteArray.class, "getInt", MethodType.methodType(int.class, byte[].class, int.class)),
|
||||||
long.class, lkp.findStatic(Bits.class, "getLong", MethodType.methodType(long.class, byte[].class, int.class)),
|
long.class, lkp.findStatic(ByteArray.class, "getLong", MethodType.methodType(long.class, byte[].class, int.class)),
|
||||||
float.class, lkp.findStatic(Bits.class, "getFloat", MethodType.methodType(float.class, byte[].class, int.class)),
|
float.class, lkp.findStatic(ByteArray.class, "getFloat", MethodType.methodType(float.class, byte[].class, int.class)),
|
||||||
double.class, lkp.findStatic(Bits.class, "getDouble", MethodType.methodType(double.class, byte[].class, int.class)),
|
double.class, lkp.findStatic(ByteArray.class, "getDouble", MethodType.methodType(double.class, byte[].class, int.class)),
|
||||||
char.class, lkp.findStatic(Bits.class, "getChar", MethodType.methodType(char.class, byte[].class, int.class)),
|
char.class, lkp.findStatic(ByteArray.class, "getChar", MethodType.methodType(char.class, byte[].class, int.class)),
|
||||||
boolean.class, lkp.findStatic(Bits.class, "getBoolean", MethodType.methodType(boolean.class, byte[].class, int.class))
|
boolean.class, lkp.findStatic(ByteArray.class, "getBoolean", MethodType.methodType(boolean.class, byte[].class, int.class))
|
||||||
);
|
);
|
||||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||||
throw new InternalError("Can't lookup Bits.getXXX", e);
|
throw new InternalError("Can't lookup " + ByteArray.class.getName() + ".getXXX", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,6 +30,7 @@ import java.nio.channels.FileChannel;
|
|||||||
import jdk.internal.access.JavaIORandomAccessFileAccess;
|
import jdk.internal.access.JavaIORandomAccessFileAccess;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.misc.Blocker;
|
import jdk.internal.misc.Blocker;
|
||||||
|
import jdk.internal.util.ByteArray;
|
||||||
import sun.nio.ch.FileChannelImpl;
|
import sun.nio.ch.FileChannelImpl;
|
||||||
|
|
||||||
|
|
||||||
@ -884,7 +885,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
*/
|
*/
|
||||||
public final int readInt() throws IOException {
|
public final int readInt() throws IOException {
|
||||||
readFully(buffer, 0, Integer.BYTES);
|
readFully(buffer, 0, Integer.BYTES);
|
||||||
return Bits.getInt(buffer, 0);
|
return ByteArray.getInt(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -917,7 +918,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
*/
|
*/
|
||||||
public final long readLong() throws IOException {
|
public final long readLong() throws IOException {
|
||||||
readFully(buffer, 0, Long.BYTES);
|
readFully(buffer, 0, Long.BYTES);
|
||||||
return Bits.getLong(buffer, 0);
|
return ByteArray.getLong(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -941,7 +942,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
*/
|
*/
|
||||||
public final float readFloat() throws IOException {
|
public final float readFloat() throws IOException {
|
||||||
readFully(buffer, 0, Float.BYTES);
|
readFully(buffer, 0, Float.BYTES);
|
||||||
return Bits.getFloat(buffer, 0);
|
return ByteArray.getFloat(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -965,7 +966,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
*/
|
*/
|
||||||
public final double readDouble() throws IOException {
|
public final double readDouble() throws IOException {
|
||||||
readFully(buffer, 0, Double.BYTES);
|
readFully(buffer, 0, Double.BYTES);
|
||||||
return Bits.getDouble(buffer, 0);
|
return ByteArray.getDouble(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1104,7 +1105,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public final void writeInt(int v) throws IOException {
|
public final void writeInt(int v) throws IOException {
|
||||||
Bits.putInt(buffer, 0, v);
|
ByteArray.setInt(buffer, 0, v);
|
||||||
write(buffer, 0, Integer.BYTES);
|
write(buffer, 0, Integer.BYTES);
|
||||||
//written += 4;
|
//written += 4;
|
||||||
}
|
}
|
||||||
@ -1117,7 +1118,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public final void writeLong(long v) throws IOException {
|
public final void writeLong(long v) throws IOException {
|
||||||
Bits.putLong(buffer, 0, v);
|
ByteArray.setLong(buffer, 0, v);
|
||||||
write(buffer, 0, Long.BYTES);
|
write(buffer, 0, Long.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,7 +1134,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
* @see java.lang.Float#floatToIntBits(float)
|
* @see java.lang.Float#floatToIntBits(float)
|
||||||
*/
|
*/
|
||||||
public final void writeFloat(float v) throws IOException {
|
public final void writeFloat(float v) throws IOException {
|
||||||
writeInt(Float.floatToIntBits(v));
|
ByteArray.setFloat(buffer, 0, v);
|
||||||
|
write(buffer, 0, Float.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1148,7 +1150,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
|||||||
* @see java.lang.Double#doubleToLongBits(double)
|
* @see java.lang.Double#doubleToLongBits(double)
|
||||||
*/
|
*/
|
||||||
public final void writeDouble(double v) throws IOException {
|
public final void writeDouble(double v) throws IOException {
|
||||||
writeLong(Double.doubleToLongBits(v));
|
ByteArray.setDouble(buffer, 0, v);
|
||||||
|
write(buffer, 0, Double.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
424
src/java.base/share/classes/jdk/internal/util/ByteArray.java
Normal file
424
src/java.base/share/classes/jdk/internal/util/ByteArray.java
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jdk.internal.util;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for packing/unpacking primitive values in/out of byte arrays
|
||||||
|
* using {@linkplain ByteOrder#BIG_ENDIAN big endian order} (aka. "network order").
|
||||||
|
* <p>
|
||||||
|
* All methods in this class will throw an {@linkplain NullPointerException} if {@code null} is
|
||||||
|
* passed in as a method parameter for a byte array.
|
||||||
|
*/
|
||||||
|
public final class ByteArray {
|
||||||
|
|
||||||
|
private ByteArray() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final VarHandle SHORT = create(short[].class);
|
||||||
|
private static final VarHandle CHAR = create(char[].class);
|
||||||
|
private static final VarHandle INT = create(int[].class);
|
||||||
|
private static final VarHandle FLOAT = create(float[].class);
|
||||||
|
private static final VarHandle LONG = create(long[].class);
|
||||||
|
private static final VarHandle DOUBLE = create(double[].class);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods for unpacking primitive values from byte arrays starting at
|
||||||
|
* a given offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code boolean} from the provided {@code array} at the given {@code offset}}.
|
||||||
|
*
|
||||||
|
* @param array to read a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 1]
|
||||||
|
* @see #setBoolean(byte[], int, boolean)
|
||||||
|
*/
|
||||||
|
public static boolean getBoolean(byte[] array, int offset) {
|
||||||
|
return array[offset] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code char} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #setChar(byte[], int, char)
|
||||||
|
*/
|
||||||
|
public static char getChar(byte[] array, int offset) {
|
||||||
|
return (char) CHAR.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code short} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @return a {@code short} from the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #setShort(byte[], int, short)
|
||||||
|
*/
|
||||||
|
public static short getShort(byte[] array, int offset) {
|
||||||
|
return (short) SHORT.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return an {@code unsigned short} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @return an {@code int} representing an unsigned short from the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #setUnsignedShort(byte[], int, int)
|
||||||
|
*/
|
||||||
|
public static int getUnsignedShort(byte[] array, int offset) {
|
||||||
|
return Short.toUnsignedInt((short) SHORT.get(array, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return an {@code int} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 4]
|
||||||
|
* @see #setInt(byte[], int, int)
|
||||||
|
*/
|
||||||
|
public static int getInt(byte[] array, int offset) {
|
||||||
|
return (int) INT.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code float} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Float#NaN } values are canonized to a single NaN value.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 4]
|
||||||
|
* @see #setFloat(byte[], int, float)
|
||||||
|
*/
|
||||||
|
public static float getFloat(byte[] array, int offset) {
|
||||||
|
// Using Float.intBitsToFloat collapses NaN values to a single
|
||||||
|
// "canonical" NaN value
|
||||||
|
return Float.intBitsToFloat((int) INT.get(array, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code float} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Float#NaN } values are silently read according
|
||||||
|
* to their bit patterns.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 4]
|
||||||
|
* @see #setFloatRaw(byte[], int, float)
|
||||||
|
*/
|
||||||
|
public static float getFloatRaw(byte[] array, int offset) {
|
||||||
|
// Just gets the bits as they are
|
||||||
|
return (float) FLOAT.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code long} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 8]
|
||||||
|
* @see #setLong(byte[], int, long)
|
||||||
|
*/
|
||||||
|
public static long getLong(byte[] array, int offset) {
|
||||||
|
return (long) LONG.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code double} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Double#NaN } values are canonized to a single NaN value.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 8]
|
||||||
|
* @see #setDouble(byte[], int, double)
|
||||||
|
*/
|
||||||
|
public static double getDouble(byte[] array, int offset) {
|
||||||
|
// Using Double.longBitsToDouble collapses NaN values to a single
|
||||||
|
// "canonical" NaN value
|
||||||
|
return Double.longBitsToDouble((long) LONG.get(array, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a {@code double} from the provided {@code array} at the given {@code offset}
|
||||||
|
* using big endian order}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Double#NaN } values are silently read according to
|
||||||
|
* their bit patterns.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to get a value from.
|
||||||
|
* @param offset where extraction in the array should begin
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 8]
|
||||||
|
* @see #setDoubleRaw(byte[], int, double)
|
||||||
|
*/
|
||||||
|
public static double getDoubleRaw(byte[] array, int offset) {
|
||||||
|
// Just gets the bits as they are
|
||||||
|
return (double) DOUBLE.get(array, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods for packing primitive values into byte arrays starting at a given
|
||||||
|
* offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length]
|
||||||
|
* @see #getBoolean(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setBoolean(byte[] array, int offset, boolean value) {
|
||||||
|
array[offset] = (byte) (value ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getChar(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setChar(byte[] array, int offset, char value) {
|
||||||
|
CHAR.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getShort(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setShort(byte[] array, int offset, short value) {
|
||||||
|
SHORT.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getUnsignedShort(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setUnsignedShort(byte[] array, int offset, int value) {
|
||||||
|
SHORT.set(array, offset, (short) (char) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 4]
|
||||||
|
* @see #getInt(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setInt(byte[] array, int offset, int value) {
|
||||||
|
INT.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Float#NaN } values are canonized to a single NaN value.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getFloat(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setFloat(byte[] array, int offset, float value) {
|
||||||
|
// Using Float.floatToIntBits collapses NaN values to a single
|
||||||
|
// "canonical" NaN value
|
||||||
|
INT.set(array, offset, Float.floatToIntBits(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Float#NaN } values are silently written according to
|
||||||
|
* their bit patterns.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getFloatRaw(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setFloatRaw(byte[] array, int offset, float value) {
|
||||||
|
// Just sets the bits as they are
|
||||||
|
FLOAT.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 4]
|
||||||
|
* @see #getLong(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setLong(byte[] array, int offset, long value) {
|
||||||
|
LONG.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Double#NaN } values are canonized to a single NaN value.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getDouble(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setDouble(byte[] array, int offset, double value) {
|
||||||
|
// Using Double.doubleToLongBits collapses NaN values to a single
|
||||||
|
// "canonical" NaN value
|
||||||
|
LONG.set(array, offset, Double.doubleToLongBits(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (writes) the provided {@code value} using big endian order into
|
||||||
|
* the provided {@code array} beginning at the given {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* Variants of {@linkplain Double#NaN } values are silently written according to
|
||||||
|
* their bit patterns.
|
||||||
|
* <p>
|
||||||
|
* There are no access alignment requirements.
|
||||||
|
*
|
||||||
|
* @param array to set (write) a value into
|
||||||
|
* @param offset where setting (writing) in the array should begin
|
||||||
|
* @param value value to set in the array
|
||||||
|
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
|
||||||
|
* the range [0, array.length - 2]
|
||||||
|
* @see #getDoubleRaw(byte[], int)
|
||||||
|
*/
|
||||||
|
public static void setDoubleRaw(byte[] array, int offset, double value) {
|
||||||
|
// Just sets the bits as they are
|
||||||
|
DOUBLE.set(array, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VarHandle create(Class<?> viewArrayClass) {
|
||||||
|
return MethodHandles.byteArrayViewVarHandle(viewArrayClass, ByteOrder.BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.io;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to allow public access to package-private methods.
|
|
||||||
*/
|
|
||||||
public final class BitsProxy {
|
|
||||||
|
|
||||||
public static boolean getBoolean(byte[] b, int off) {
|
|
||||||
return Bits.getBoolean(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char getChar(byte[] b, int off) {
|
|
||||||
return Bits.getChar(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static short getShort(byte[] b, int off) {
|
|
||||||
return Bits.getShort(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getInt(byte[] b, int off) {
|
|
||||||
return Bits.getInt(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float getFloat(byte[] b, int off) {
|
|
||||||
return Bits.getFloat(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long getLong(byte[] b, int off) {
|
|
||||||
return Bits.getLong(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double getDouble(byte[] b, int off) {
|
|
||||||
return Bits.getDouble(b, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void putBoolean(byte[] b, int off, boolean val) {
|
|
||||||
Bits.putBoolean(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putChar(byte[] b, int off, char val) {
|
|
||||||
Bits.putChar(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putShort(byte[] b, int off, short val) {
|
|
||||||
Bits.putShort(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putInt(byte[] b, int off, int val) {
|
|
||||||
Bits.putInt(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putFloat(byte[] b, int off, float val) {
|
|
||||||
Bits.putFloat(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putLong(byte[] b, int off, long val) {
|
|
||||||
Bits.putLong(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putDouble(byte[] b, int off, double val) {
|
|
||||||
Bits.putDouble(b, off, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -24,19 +24,19 @@
|
|||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8299576
|
* @bug 8299576
|
||||||
|
* @modules java.base/jdk.internal.util
|
||||||
* @summary Verify that reads and writes of primitives are correct
|
* @summary Verify that reads and writes of primitives are correct
|
||||||
* @compile/module=java.base java/io/BitsProxy.java
|
|
||||||
* @run junit ReadWriteValues
|
* @run junit ReadWriteValues
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.BitsProxy;
|
import jdk.internal.util.ByteArray;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import java.util.stream.DoubleStream;
|
import java.util.stream.DoubleStream;
|
||||||
import java.util.stream.LongStream;
|
import java.util.stream.LongStream;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
final class ReadWriteValues {
|
final class ReadWriteValues {
|
||||||
@ -53,7 +53,7 @@ final class ReadWriteValues {
|
|||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
short expected = (short) l;
|
short expected = (short) l;
|
||||||
RefImpl.putShort(BUFF, OFFSET, expected);
|
RefImpl.putShort(BUFF, OFFSET, expected);
|
||||||
short actual = BitsProxy.getShort(BUFF, OFFSET);
|
short actual = ByteArray.getShort(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ final class ReadWriteValues {
|
|||||||
void testPutShort() {
|
void testPutShort() {
|
||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
short expected = (short) l;
|
short expected = (short) l;
|
||||||
BitsProxy.putShort(BUFF, OFFSET, expected);
|
ByteArray.setShort(BUFF, OFFSET, expected);
|
||||||
short actual = RefImpl.getShort(BUFF, OFFSET);
|
short actual = RefImpl.getShort(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
@ -73,7 +73,7 @@ final class ReadWriteValues {
|
|||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
char expected = (char) l;
|
char expected = (char) l;
|
||||||
RefImpl.putChar(BUFF, OFFSET, expected);
|
RefImpl.putChar(BUFF, OFFSET, expected);
|
||||||
char actual = BitsProxy.getChar(BUFF, OFFSET);
|
char actual = ByteArray.getChar(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ final class ReadWriteValues {
|
|||||||
void testPutChar() {
|
void testPutChar() {
|
||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
char expected = (char) l;
|
char expected = (char) l;
|
||||||
BitsProxy.putChar(BUFF, OFFSET, expected);
|
ByteArray.setChar(BUFF, OFFSET, expected);
|
||||||
char actual = RefImpl.getChar(BUFF, OFFSET);
|
char actual = RefImpl.getChar(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
@ -93,7 +93,7 @@ final class ReadWriteValues {
|
|||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
int expected = (int) l;
|
int expected = (int) l;
|
||||||
RefImpl.putInt(BUFF, OFFSET, expected);
|
RefImpl.putInt(BUFF, OFFSET, expected);
|
||||||
int actual = BitsProxy.getInt(BUFF, OFFSET);
|
int actual = ByteArray.getInt(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ final class ReadWriteValues {
|
|||||||
void testPutInt() {
|
void testPutInt() {
|
||||||
longs().forEach(l -> {
|
longs().forEach(l -> {
|
||||||
int expected = (int) l;
|
int expected = (int) l;
|
||||||
BitsProxy.putInt(BUFF, OFFSET, expected);
|
ByteArray.setInt(BUFF, OFFSET, expected);
|
||||||
int actual = RefImpl.getInt(BUFF, OFFSET);
|
int actual = RefImpl.getInt(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
@ -112,7 +112,7 @@ final class ReadWriteValues {
|
|||||||
void testGetLong() {
|
void testGetLong() {
|
||||||
longs().forEach(expected -> {
|
longs().forEach(expected -> {
|
||||||
RefImpl.putLong(BUFF, OFFSET, expected);
|
RefImpl.putLong(BUFF, OFFSET, expected);
|
||||||
long actual = BitsProxy.getLong(BUFF, OFFSET);
|
long actual = ByteArray.getLong(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ final class ReadWriteValues {
|
|||||||
@Test
|
@Test
|
||||||
void testPutLong() {
|
void testPutLong() {
|
||||||
longs().forEach(expected -> {
|
longs().forEach(expected -> {
|
||||||
BitsProxy.putLong(BUFF, OFFSET, expected);
|
ByteArray.setLong(BUFF, OFFSET, expected);
|
||||||
long actual = RefImpl.getLong(BUFF, OFFSET);
|
long actual = RefImpl.getLong(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
@ -130,7 +130,7 @@ final class ReadWriteValues {
|
|||||||
void testGetFloat() {
|
void testGetFloat() {
|
||||||
floats().forEach(expected -> {
|
floats().forEach(expected -> {
|
||||||
RefImpl.putFloat(BUFF, OFFSET, expected);
|
RefImpl.putFloat(BUFF, OFFSET, expected);
|
||||||
float actual = BitsProxy.getFloat(BUFF, OFFSET);
|
float actual = ByteArray.getFloat(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ final class ReadWriteValues {
|
|||||||
@Test
|
@Test
|
||||||
void testPutFloat() {
|
void testPutFloat() {
|
||||||
floats().forEach(expected -> {
|
floats().forEach(expected -> {
|
||||||
BitsProxy.putFloat(BUFF, OFFSET, expected);
|
ByteArray.setFloat(BUFF, OFFSET, expected);
|
||||||
float actual = RefImpl.getFloat(BUFF, OFFSET);
|
float actual = RefImpl.getFloat(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
@ -148,7 +148,7 @@ final class ReadWriteValues {
|
|||||||
void testGetDouble() {
|
void testGetDouble() {
|
||||||
doubles().forEach(expected -> {
|
doubles().forEach(expected -> {
|
||||||
RefImpl.putDouble(BUFF, OFFSET, expected);
|
RefImpl.putDouble(BUFF, OFFSET, expected);
|
||||||
double actual = BitsProxy.getDouble(BUFF, OFFSET);
|
double actual = ByteArray.getDouble(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -156,31 +156,183 @@ final class ReadWriteValues {
|
|||||||
@Test
|
@Test
|
||||||
void testPutDouble() {
|
void testPutDouble() {
|
||||||
doubles().forEach(expected -> {
|
doubles().forEach(expected -> {
|
||||||
BitsProxy.putDouble(BUFF, OFFSET, expected);
|
ByteArray.setDouble(BUFF, OFFSET, expected);
|
||||||
double actual = RefImpl.getDouble(BUFF, OFFSET);
|
double actual = RefImpl.getDouble(BUFF, OFFSET);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutUnsignedShort() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
int expected = Short.toUnsignedInt((short) l);
|
||||||
|
ByteArray.setUnsignedShort(BUFF, OFFSET, expected);
|
||||||
|
int actual = Short.toUnsignedInt(RefImpl.getShort(BUFF, OFFSET));
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Unusual cases
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNullArray() {
|
||||||
|
assertThrowsOriginal(NullPointerException.class, () -> ByteArray.getInt(null, OFFSET));
|
||||||
|
assertThrowsOriginal(NullPointerException.class, () -> ByteArray.setInt(null, OFFSET, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNegArg() {
|
||||||
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.getInt(BUFF, -1));
|
||||||
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.setInt(BUFF, -1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testOutOfBounds() {
|
||||||
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.getInt(BUFF, BUFF.length));
|
||||||
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.setInt(BUFF, BUFF.length, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// At-zero methods
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetShortAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
short expected = (short) l;
|
||||||
|
RefImpl.putShort(BUFF, 0, expected);
|
||||||
|
short actual = ByteArray.getShort(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutShortAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
short expected = (short) l;
|
||||||
|
ByteArray.setShort(BUFF, expected);
|
||||||
|
short actual = RefImpl.getShort(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetCharAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
char expected = (char) l;
|
||||||
|
RefImpl.putChar(BUFF, 0, expected);
|
||||||
|
char actual = ByteArray.getChar(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutCharAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
char expected = (char) l;
|
||||||
|
ByteArray.setChar(BUFF, expected);
|
||||||
|
char actual = RefImpl.getChar(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetIntAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
int expected = (int) l;
|
||||||
|
RefImpl.putInt(BUFF, 0, expected);
|
||||||
|
int actual = ByteArray.getInt(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutIntAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
int expected = (int) l;
|
||||||
|
ByteArray.setInt(BUFF, expected);
|
||||||
|
int actual = RefImpl.getInt(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetLongAtZero() {
|
||||||
|
longs().forEach(expected -> {
|
||||||
|
RefImpl.putLong(BUFF, 0, expected);
|
||||||
|
long actual = ByteArray.getLong(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutLongAtZero() {
|
||||||
|
longs().forEach(expected -> {
|
||||||
|
ByteArray.setLong(BUFF, expected);
|
||||||
|
long actual = RefImpl.getLong(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetFloatAtZero() {
|
||||||
|
floats().forEach(expected -> {
|
||||||
|
RefImpl.putFloat(BUFF, 0, expected);
|
||||||
|
float actual = ByteArray.getFloat(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutFloatAtZero() {
|
||||||
|
floats().forEach(expected -> {
|
||||||
|
ByteArray.setFloat(BUFF, expected);
|
||||||
|
float actual = RefImpl.getFloat(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetDoubleAtZero() {
|
||||||
|
doubles().forEach(expected -> {
|
||||||
|
RefImpl.putDouble(BUFF, 0, expected);
|
||||||
|
double actual = ByteArray.getDouble(BUFF);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutDoubleAtZero() {
|
||||||
|
doubles().forEach(expected -> {
|
||||||
|
ByteArray.setDouble(BUFF, expected);
|
||||||
|
double actual = RefImpl.getDouble(BUFF, 0);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPutUnsignedShortAtZero() {
|
||||||
|
longs().forEach(l -> {
|
||||||
|
int expected = Short.toUnsignedInt((short) l);
|
||||||
|
ByteArray.setUnsignedShort(BUFF, expected);
|
||||||
|
int actual = Short.toUnsignedInt(RefImpl.getShort(BUFF, 0));
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Unusual cases
|
// Unusual cases
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNullArray() {
|
void testNullArrayAtZero() {
|
||||||
assertThrowsOriginal(NullPointerException.class, () -> BitsProxy.getInt(null, OFFSET));
|
assertThrowsOriginal(NullPointerException.class, () -> ByteArray.getInt(null));
|
||||||
assertThrowsOriginal(NullPointerException.class, () -> BitsProxy.putInt(null, OFFSET, 1));
|
assertThrowsOriginal(NullPointerException.class, () -> ByteArray.setInt(null, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNegArg() {
|
void testOutOfBoundsAtZero() {
|
||||||
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> BitsProxy.getInt(BUFF, -1));
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.getInt(new byte[1]));
|
||||||
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> BitsProxy.putInt(BUFF, -1, 1));
|
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> ByteArray.setInt(new byte[1],1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testOutOfBounds() {
|
|
||||||
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> BitsProxy.getInt(BUFF, BUFF.length));
|
|
||||||
assertThrowsOriginal(IndexOutOfBoundsException.class, () -> BitsProxy.putInt(BUFF, BUFF.length, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static LongStream longs() {
|
static LongStream longs() {
|
||||||
return ThreadLocalRandom.current().longs(ITERATIONS);
|
return ThreadLocalRandom.current().longs(ITERATIONS);
|
||||||
@ -315,5 +467,4 @@ final class ReadWriteValues {
|
|||||||
putLong(b, off, Double.doubleToLongBits(val));
|
putLong(b, off, Double.doubleToLongBits(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*/
|
||||||
|
package org.openjdk.bench.java.io;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.TearDown;
|
||||||
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
@Fork(2)
|
||||||
|
@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
|
||||||
|
public class PrimitiveFieldSerializationBenchmark {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(PrimitiveFieldSerializationBenchmark.class.getSimpleName())
|
||||||
|
.build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
public static class Log {
|
||||||
|
|
||||||
|
MyData myData = new MyData((byte) 1, 'a', (short) 47, 1234, 0.01f, 1234L, 0.01d);
|
||||||
|
MyRecord myRecord = new MyRecord((byte) 1, 'a', (short) 47, 1234, 0.01f, 1234L, 0.01d);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputStream bos;
|
||||||
|
private ObjectOutputStream os;
|
||||||
|
|
||||||
|
@Setup
|
||||||
|
public void setupStreams(Blackhole bh) throws IOException {
|
||||||
|
bos = new BlackholeOutputStream(bh);
|
||||||
|
os = new ObjectOutputStream(bos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TearDown
|
||||||
|
public void tearDownStreams() throws IOException {
|
||||||
|
os.close();
|
||||||
|
bos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class MyData implements Serializable {
|
||||||
|
byte b;
|
||||||
|
char c;
|
||||||
|
short s;
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
long l;
|
||||||
|
double d;
|
||||||
|
|
||||||
|
public MyData(byte b, char c, short s, int i, float f, long l, double d) {
|
||||||
|
this.b = b;
|
||||||
|
this.c = c;
|
||||||
|
this.s = s;
|
||||||
|
this.i = i;
|
||||||
|
this.f = f;
|
||||||
|
this.l = l;
|
||||||
|
this.d = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MyRecord(byte b,
|
||||||
|
char c,
|
||||||
|
short s,
|
||||||
|
int i,
|
||||||
|
float f,
|
||||||
|
long l,
|
||||||
|
double d) implements Serializable {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void serializeData(Log input) throws IOException {
|
||||||
|
os.writeObject(input.myData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void serializeRecord(Log input) throws IOException {
|
||||||
|
os.writeObject(input.myRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class BlackholeOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
private final Blackhole bh;
|
||||||
|
|
||||||
|
public BlackholeOutputStream(Blackhole bh) {
|
||||||
|
this.bh = bh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) {
|
||||||
|
bh.consume(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b) {
|
||||||
|
bh.consume(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int off, int len) {
|
||||||
|
bh.consume(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user