Kilim的小BUG

简介:

[java]
public ByteBuffer fill(ByteBuffer buf, int atleastN) throws IOException, Pausable {
if (buf.remaining() < atleastN) {
ByteBuffer newbb = ByteBuffer.allocate(Math.max(buf.capacity() * 3 / 2, buf.position() + atleastN));
buf.rewind();
newbb.put(buf);
buf = newbb;
}
……
}
[/java]
后面的代码我省略了,这个BUG就出现在这段代码里。这段代码的逻辑很简单,先是创建一个新的更大的缓冲区,然后将老的缓冲区的数据put到新的缓冲区,在put之前调用rewind方法将老的缓冲区的position设置为0。查看rewind干了什么:
[java]
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
[/java]
仅仅是将position设置为0,并让mark失效。position指向下一个读或者写的位置,这里在写入到新缓冲区之前确实需要将position 设置为0,以便写入从老的缓冲区第一个位置开始。问题是什么?问题是position仅仅指定了下一个读取数据的位置,却没有指定有效数据的大小,换句话说,没有指定老的缓冲区的limit。因此这里造成的后果是老的缓冲区整个被写入到新的老缓冲区,包括有效数据和无效数据,默认情况下缓冲区的limit 等于capacity。

这个bug可以通过下面程序看出来:
[java]
ByteBuffer old = ByteBuffer.allocate(8);
old.putInt(99);
ByteBuffer newBuf = ByteBuffer.allocate(16);
old.rewind();
newBuf.put(old);
newBuf.putInt(100);

[/java]
先往old写入一个整数99,然后创建newBuf并写入old数据,并再写入一个整数100,最后从newBuf读数据。本来我们预期只应该读到两个整数99和100,但是中间却插入一个0,输出如下:

12
99
0
100

[java]
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
[/java]
修改上面的测试程序,符合我们的预期了:
[java]
ByteBuffer old = ByteBuffer.allocate(8);
old.putInt(99);
ByteBuffer newBuf = ByteBuffer.allocate(16);
old.flip();
newBuf.put(old);
newBuf.putInt(100);

[/java]
输出:
8
99
100

[java]
while (buffer.hasRemaining()) //发送数据
networkChannel.write(buffer);
buffer.rewind(); // 重置buffer,准备写入日志管道
while (buffer.hasRemaining()) // 写入日志
loggerChannel.write(buffer);
[/java]
而flip用于缓冲区发送或者读取之前,也就是将缓冲区设置为等待传出状态。

本文来源于"阿里中间件团队播客",原文发表时间"2010-11-03"

相关文章
|
2月前
|
安全 Java 测试技术
咦,出BUG了
咦,出BUG了
14 0
|
存储 Web App开发 JavaScript
一个有趣的BUG
一个有趣的BUG
73 0
一个有趣的BUG
|
JavaScript 前端开发 IDE
因为使用peerDependencies而引发的bug
因为使用peerDependencies而引发的bug
因为使用peerDependencies而引发的bug
|
JavaScript 索引
|
前端开发 程序员
BUG之虐之吐槽篇
BUG之虐之吐槽篇
73 0
BUG之虐之吐槽篇
|
消息中间件 NoSQL 程序员
这 BUG,绝了
看到这几个 BUG 之后,我的目标就改变了,不再是写出优雅的代码,而是写出巧妙的 BUG。
145 0
|
消息中间件 NoSQL Redis
修复过的一个bug
高并发的功能调用云产品时走过的路
137 0
|
程序员
佛祖镇楼,BUG避易
def FZZL(): print(" _ooOoo_ ") print(" o8888888o ") print(" 88 .
1152 0
|
Android开发
坦白说bug
安卓收藏他发的图片就可以在收藏里看到了哦 苹果直接搜索聊天记录就行了哦(人 •͈ᴗ•͈)۶比心心
633 0
|
Web App开发 前端开发 JavaScript