10

Very simple problem: I'm reading from one SocketChannel and would like to write the results to another SocketChannel. I'm using a Selector object, so I wait until one SocketChannel is readable, dump the data to a ByteBuffer, and then when the next SocketChannel is writable, I dump the ByteBuffer there. OK so far. However, it doesn't appear there is any way to actually "clear" a ByteBuffer, so I can't do any sort of check to know when new data has arrived.

I've tried the .clear() method, but that apparently doesn't clear the buffer, but just resets the buffer position to 1.

Here's some example code:

ByteBuffer channel1buf = ByteBuffer.allocate(1024);
ByteBuffer channel2buf = ByteBuffer.allocate(1024);

if (key.isReadable()) {
    if (key.channel().equals(channel1)) {
        channel1.read(channel2buf);
    } else if (key.channel().equals(channel2)) {
        channel2.read(channel1buf);
    }
} else if (key.isWritable()) {
    if (key.channel().equals(channel1) && channel1buf.asCharBuffer().length() > 0) {
        channel1.write(channel1buf);
        /* some way to clear channel1buf */
    } else /* same idea for channel2... */
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user1241397
  • 103
  • 1
  • 1
  • 4
  • You should use the `ByteBuffer` as attachment while registering the channel to the selector (third parameter of the regsiter method), that way you can retrieve the attachment from the `SelectionKey` and avoid all the nested if clauses. – mike Feb 17 '15 at 15:06

3 Answers3

8

Buffer.clear resets the position, yes, and then you can use getPosition() > 0 to check if anything has been added to the buffer afterwards, no...?

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • That _almost_ works, however the buffer still has the old data, so it'll print any overflow. I guess I could go through the buffer and clean it out manually, but that doesn't seem too elegant. – user1241397 Feb 29 '12 at 23:10
  • The point is, why do you care if the buffer still has the old data? It's not as if clearing it out would let you GC anything. Just don't look at anything below the `getPosition()` and you should be fine...or is there something I'm missing? – Louis Wasserman Feb 29 '12 at 23:19
  • Well, the buffer is some fixed size, so if I do that I'd eventually run out of space in the buffer. – user1241397 Feb 29 '12 at 23:26
  • 1
    Not true. When you call `Buffer.clear()`, it resets the write position to 0, so any new writes into the buffer will just write over the old data that you cleared. – Louis Wasserman Feb 29 '12 at 23:27
  • Ah, got it! Wasn't sure what direction "below" was referring too :-). – user1241397 Feb 29 '12 at 23:32
  • Can the use of ByteBuffer lead to the Out of memory? Is memory cleared if you execute clear()? – DuosDuo Jul 08 '19 at 10:55
  • @DuosDuo yes, they can cause an OOM, if you allocate enough of them *and hold on to them.*. No, calling clear() does nothing to reclaim the memory; letting them drop out of scope and removing references to them does. ByteBuffers are like any other Java object. – Louis Wasserman Jul 08 '19 at 16:14
  • After a long work, we have a device crash and it reboots. But the device only displays the boot screen and reboots back (the OS does not boot completely). Can the out-of-memory cause such consequences? Or can this happen if we very often (every second) create a bytebuffer? Can something happen to the memory? Or something different? You will help me a lot with your opinion!) thank! – DuosDuo Jul 08 '19 at 16:40
6

I resolved a same problem by this code, hope it can help you.

channel1buf.clear();
//zerolize buff manually
channel1buf.put(new byte[1024]);
channel1buf.clear();
waveacme
  • 311
  • 3
  • 4
  • 1
    But this sort of `ZeroMemory()` for a buffer is not needed if you use the `ByteBuffer` class the way it is intended to be used, which is by calling `flip()` before reading, `rewind()` before re-reading, `clear()` or `compact()` before writing. – Lumi Feb 04 '14 at 23:11
2

IMO, allocation new memory(channel1buf.put(new byte[1024]);)

is not a better solution to follow.

You can use following code segment:

java.util.Arrays.fill(channel1buff.array(), (byte)0);
SuRa
  • 1,053
  • 9
  • 13