Consider the following:
```
try (FileChannel fc = FileChannel.open(file, CREATE, WRITE)) {
OutputStream out = Channels.newOutputStream(fc);
byte[] b = new byte[10*1024*1024];
out.write(b);
}
```
This will invoke FileChannel.write with a BB that is backed by the byte array, this needs to be copied into a direct buffer to do the actual I/O. In this case, it will allocate a temporary direct buffer of 10Mb.
There is an argument that the channel implementations should limit their direct memory usage but these are low-level classes. It may be better to limit the writes to the channels instead, e.g. ChannelOutputStream.writeFully could be work like this:
```
private void writeFully(ByteBuffer bb) throws IOException {
int pos = bb.position();
int rem = bb.limit() - pos;
while (rem > 0) {
bb.limit(pos + Integer.min(rem, DEFAULT_BUFFER_SIZE));
int n = ch.write(bb);
if (n <= 0)
throw new RuntimeException("no bytes written");
pos += n;
rem -=n;
}
}
```