扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
翻译为缓冲,是一块可以读写的区域。
专业网站设计公司,专做排名好的好网站,排在同行前面,为您带来客户和效益!成都创新互联公司为您提供品质好成都网站建设,五站合一网站设计制作,服务好的网站设计公司,负责任的成都网站制作公司!为什么需要缓冲?思考:没有buffer之前的读写。
方法抽象方法
//是否只读
public abstract boolean isReadOnly();
//判断有没有数组
public abstract boolean hasArray();
//返回数组
public abstract Object array();
//返回数组偏移
public abstract int arrayOffset();
//是否是直接缓冲区
public abstract boolean isDirect();
//切分
public abstract Buffer slice();
//切分
public abstract Buffer slice(int index, int length);
//复制一个buffer
public abstract Buffer duplicate();
//
abstract Object base();
构造函数
Buffer(long addr, int cap, MemorySegmentProxy segment) {this.address = addr;
this.capacity = cap;
this.segment = segment;
}
Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private
if (cap< 0)
throw createCapacityException(cap);
this.capacity = cap;
this.segment = segment;
limit(lim);
position(pos);
if (mark >= 0) {if (mark >pos)
throw new IllegalArgumentException("mark >position: ("
+ mark + ">" + pos + ")");
this.mark = mark;
}
}
普通方法
在这里插入代码片
字段
static final Unsafe UNSAFE = Unsafe.getUnsafe();
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
static final int SPLITERATOR_CHARACTERISTICS =
Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
long address;
// Used by buffers generated by the memory access API (JEP-370)
final MemorySegmentProxy segment;
子类
常见类型的缓冲
public abstract class ByteBuffer
extends Buffer
implements Comparable{}
ByteBuffer是抽象类无法直接实例化,可以通过allocate等方法返回实例。
allocate
public static ByteBuffer allocate(int capacity) {if (capacity< 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
allocateDirect
public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);
}
ByteBuffer 分为HeapByteBuffer和DirectByteBuffer两种,翻译成人话就是堆字节缓冲和直接字节缓冲,第二种不受 JVM 控制。
ByteBuffer hbb = ByteBuffer.allocate(1024);
ByteBuffer dbb = ByteBuffer.allocateDirect(1024);
在后面的介绍中,hbb代指 JVM 缓冲区,dbb代指直接缓冲区。
HeapByteBuffer DirectByteBuffer 常见方法 allocate下面对 allocate 的调用链路参数进行分析。
public static ByteBuffer allocate(int capacity) {if (capacity< 0)
throw new IllegalArgumentException();
//capacity >= 0
return new HeapByteBuffer(capacity, capacity);
}
cap = lim = capacity,由 HeapByteBuffer 构造函数调用 super
HeapByteBuffer(int cap, int lim) {
super(-1, 0, lim, cap, new byte[cap], 0);
}
mark = -1
pos = 0
lim = cap
cap = cap
hb = new byte[cap]
offset = 0
ByteBuffer(int mark, int pos, int lim, int cap,
byte[] hb, int offset)
{super(mark, pos, lim, cap); //-1,0,cap,cap
this.hb = hb; //new byte[cap]
this.offset = offset; //0
}
hb字节数组和offset 偏移量为 ByteBuffer 字段。
mark = -1
pos = 0
lim = cap
cap = cap
Buffer(int mark, int pos, int lim, int cap) { //判断多余 cap >0
if (cap< 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap; // 1
limit(lim); //2
position(pos); //3
//汇总分析的参数 mark = -1,pos = 0
if (mark >= 0) {if (mark >pos)
throw new IllegalArgumentException("mark >position: ("
+ mark + ">" + pos + ")");
this.mark = mark;
}
}
核心代码表示为1,2,3的部分。
public final Buffer limit(int newLimit) {// newLimit = lim = cap
if ((newLimit >capacity) || (newLimit< 0))
throw new IllegalArgumentException();
limit = newLimit; //limit = newLimit = lim = cap
if (position >limit) position = limit; // position = 0 limit = cap
if (mark >limit) mark = -1; // mark = -1
return this;
}
public final Buffer position(int newPosition) {// newPosition = pos = pos = 0
if ((newPosition >limit) || (newPosition< 0))
throw new IllegalArgumentException();
position = newPosition; // position = newPosition = pos = pos = 0
if (mark >position) mark = -1;
return this;
}
所以经过这一串构造函数后,buffer中的值分别为
java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
pos = 位置,lim = 限制,cap = 容量,大值。
allocateDirectpublic static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);
}
DirectByteBuffer(int cap) {//cap = capacity
//调用链路
super(-1, 0, cap, cap);
//
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
Bits.reserveMemory(size, cap);
long base = 0;
try { //unsafe 分配内存空间
base = unsafe.allocateMemory(size);
} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);
throw x;
}
unsafe.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {// Round up to page boundary
address = base + ps - (base & (ps - 1));
} else {address = base;
}
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
att = null;
}
MappedByteBuffer(int mark, int pos, int lim, int cap) {// package-private
super(mark, pos, lim, cap);
this.fd = null;
}
ByteBuffer(int mark, int pos, int lim, int cap) {// package-private
this(mark, pos, lim, cap, null, 0);
}
ByteBuffer(int mark, int pos, int lim, int cap, // package-private
byte[] hb, int offset)
{super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}
Buffer(int mark, int pos, int lim, int cap) { // package-private
if (cap< 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap;
limit(lim);
position(pos);
if (mark >= 0) {if (mark >pos)
throw new IllegalArgumentException("mark >position: ("
+ mark + ">" + pos + ")");
this.mark = mark;
}
}
调用过程不再赘述,跟 allocate 链路差不多,区别是使用 unsafe 进行内存分配和其他的操作。
flip 翻转public final Buffer flip() {limit = position;
position = 0;
mark = -1;
return this;
}
案例
ByteBuffer hbb = ByteBuffer.allocate(1024);
System.out.println(hbb.toString());
hbb.flip();
System.out.println(hbb.toString());
输出
java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=0 cap=1024]
hasRemaining 是否有剩余public final boolean hasRemaining() {return position< limit;
}
position< limit 代表有剩余,position = limit 代表空间已经满了
clear 清除public final Buffer clear() {position = 0;
limit = capacity;
mark = -1;
return this;
}
将buffer三个指针位置重置。
gethbb
final byte[] hb;
public byte get() {return hb[ix(nextGetIndex())];
}
dbb
public byte get() {return ((unsafe.getByte(ix(nextGetIndex()))));
}
asReadOnlyBuffer 只读bufferpublic ByteBuffer asReadOnlyBuffer() {return new HeapByteBufferR(hb, this.markValue(), this.position(), this.limit(),
this.capacity(), offset);
}
buffer 案例1 基本操作读和写创建5个容量的buffer,依次将i放进去,翻转buf,依次读出来。
public class byteBuffer02 {public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(5);
for (byte i = 0; i< buffer.capacity(); i++) {buffer.put(i);
}
buffer.flip();
while (buffer.hasRemaining()) {System.out.println(buffer.get());
}
}
}
buffer 案例2 不同类型数据读写public class ByteBuffer03 {public static void main(String[] args) {ByteBuffer bb = ByteBuffer.allocate(64);
bb.putInt(100);
bb.putLong(9);
bb.putChar('a');
bb.putShort((short) 4);
bb.flip();
System.out.println("----");
System.out.println(bb.getInt());
System.out.println(bb.getLong());
System.out.println(bb.getChar());
System.out.println(bb.getShort());
}
}
buffer 案例3 只读 bufferpublic class ByteBuffer04 {public static void main(String[] args) {ByteBuffer b1 = ByteBuffer.allocate(64);
ByteBuffer b2 = b1.asReadOnlyBuffer();
b1.putInt(5);
b2.putInt(5);
}
}
MappedByteBuffer深入浅出java.nio.MappedByteBuffer
Channel 通道实现
源码
public interface Channel extends Closeable {//是否开启
public boolean isOpen();
//关闭
public void close() throws IOException;
}
FileChannel
开启通道的几种方式static File file = new File("D://a.txt");
从 RandomAccessFile 中getChannelRandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fc = raf.getChannel();
从 stream 中 getChannelFileOutputStream fos = new FileOutputStream(file);
FileChannel fc2 = fos.getChannel();
FileChannel.openFileChannel fc3 = FileChannel.open(null, null);
案例1将 uuid 读出来
public class ReadFileUid {static File file = new File("D://a.txt");
public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);
try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fc = raf.getChannel()) {int read = fc.read(bf);
System.out.println(read);
System.out.println(bf);
bf.flip();
System.out.println(bf);
byte[] bytes = new byte[bf.limit()];
bf.get(bytes);
System.out.println(bf);
System.out.println(Arrays.toString(bytes));
String str = new String(bytes, StandardCharsets.UTF_8);
System.out.println(str);
}
}
}
输出
36
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=36 cap=1024]
[54, 51, 51, 53, 98, 102, 53, 97, 45,
99, 57, 100, 54, 45, 52, 53, 51, 99,
45, 98, 57, 99, 98, 45, 102, 50, 52,
102, 56, 97, 54, 101, 98, 50, 99, 50]
6335bf5a-c9d6-453c-b9cb-f24f8a6eb2c2
案例2将 uuid 写到文件中
public class WriteFileUid {static File file = new File("D://a.txt");
public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);
try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fc = raf.getChannel()) {String uuid = UUID.randomUUID().toString();
System.out.println(uuid);
byte[] bytes = uuid.getBytes(StandardCharsets.UTF_8);
System.out.println(Arrays.toString(bytes));
System.out.println(bf);
bf.put(bytes);
System.out.println(bf);
bf.flip();
System.out.println(bf);
int write = fc.write(bf);
System.out.println(write);
}
}
}
efdd8059-4f47-42e9-b9f9-aadd4a324309
[101, 102, 100, 100, 56, 48, 53, 57, 45, 52, 102, 52, 55,
45, 52, 50, 101, 57, 45, 98, 57, 102, 57, 45, 97, 97,
100, 100, 52, 97, 51, 50, 52, 51, 48, 57]
java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
36
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流