- Yazılmış bir nesneyi tekrar yazmaya hazır hale getirmek için clear() metodu kullanılır.
Bellek YaratmaBu sınıf mevcut bir byte[] nesnesini wrap() metodu ile sarmalayabilir, ya da allocate metodu ile bir bellek alanı yaratabilir. Yaratılan belleğin boyu sabittir ve
büyümez!
Packing Görevi
putX() metodları ile yazma işlemi yapılır. getX() metodları ile okuma işlemi yapılır.
Yani putShort() çağrısı ile iki tane short değer yazıp getInt() metodu ile int değer okunabilir. Kısaca
packing two shorts diyelim.
allocate metodu
Heap'te yaşayan bir bellek yaratır.
Örnek
Şöyle
yaparız.
ByteBuffer bb = ByteBuffer.allocate(4);
allocateDirect metodu - off-heap/native/direct olarak tabir edilen bellek yaratır
Açıklaması
şöyle. Bir DirectByteBuffer nesnesi yaratır.
The contents of direct buffers may reside outside of the normal garbage-collected heap
Açıklaması
şöyle.
When such an object is created, it makes an internal call that allocates the amount of native memory equal to the buffer capacity. This memory is released when this class’ equivalent of “finalize” Java method is called — either automatically, when the DirectByteBuffer instance is GCed, or manually, which is rare.
Bellek alanı Java Heap dışında olsa bile, nesnenin kendisi halen JVM içinde yaşadığı için GC başlayıncaya kadar nesne
silinmez.
Direct ByteBuffer objects clean up their native buffers automatically but can only do so as part of Java heap GC — so they do not automatically respond to pressure on the native heap. GC occurs only when the Java heap becomes so full it can't service a heap-allocation request or if the Java application explicitly requests it (not recommended because it causes performance problems).
DirectByteBuffer nesnesin kullandığı belleğe, işletim sistemi erişebilir. Bazı kısıtlar
şöyle.
The ByteBuffer API allows the creation of direct, off-heap byte buffers. These buffers can be directly accessed from a Java program. However, there are some limitations:
- The buffer size can't be more than two gigabytes
- The garbage collector is responsible for memory deallocation
Furthermore, incorrect use of a ByteBuffer can cause a memory leak and OutOfMemory errors. This is because an unused memory reference can prevent the garbage collector from deallocating the memory.
array metodu
Eğer allocate metodu ile bellek alanı yaratılmışsa, bu alana erişmek için kullanılır. Şöyle
yaparız. Bu metod okuma yazma pozisyonuna dikkat etmez. Tüm dizi bellek alanını
döndürür.
byte[] result = bb.array();
arrayOffset metodu
Şöyle
yaparız.
int arrayOffset = bb.arrayOffset();
asDoubleBuffer metodu
Şöyle
yaparız.
ByteBuffer bb = ...;
DoubleBuffer db = bb.asDoubleBuffer();
clear metodu - Yazmaya Hazır Hale Getirir
Buffer nesnesinin pozisyon değerini 0 yapar. Yani daha önce kullanılmış bir nesneyi tekrar yazmaya hazır hale getirir. flip() metodunun tersi diye düşünülebilir.
Örnek
Eğer clear metodunu çağırmazsak nesne dolunca tekrar yazmak mümkün olmaz. Şu kod yazma işleminden sonra tekrar yazmaya hazır hale getirmediği için
yanlış.
FileChannel fileChannel = FileChannel.open(Paths.get("input.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (fileChannel.read(byteBuffer) != -1) {
byteBuffer.flip(); //Okumaya hazır hale getir.
while (byteBuffer.hasRemaining()) {
char c = (char)byteBuffer.get();
System.out.println(c);
}
}
Şöyle
yaparız.
FileChannel fileChannel = FileChannel.open(Paths.get("JPPFConfiguration.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int n;
while ((n = fileChannel.read(byteBuffer)) != -1) {
byteBuffer.flip(); //Okumaya hazır hale getir.
while (byteBuffer.hasRemaining()) {
char c = (char) byteBuffer.get();
System.out.print(c);
}
byteBuffer.clear(); //Yazmaya hazır hale getir
}
Örnek
Şöyle
yaparız.
ByteBuffer bb = ...;
bb.clear();
Örnek
Şöyle
yaparız.
ByteBuffer b = new ByteBuffer(1024);
for(int i=0; i<N; i++) {
b.clear(); //Make ready for write
b.put(header[i]);
b.put(data[i]);
b.flip(); //Make ready for read
out.write(b);
}
compact metodu
Açıklaması şöyle
Most writable buffers support a compact() method:
Compacting shifts any remaining data in the buffer to the start of buffer, freeing up more space for elements. Any data that was in those positions will be overwritten. The buffer's position is set to the end of data so it's ready for writing more data.
Compaction is an especially useful operation when you're copying-reading from one channel and writing data to another using non-blocking I/O. You can read some data into a buffer, write the buffer out again, then compact the data so all the data that wasn't written is at the beginning of the buffer, and the position is at the end of the data remaining in the buffer, ready to receive more data.
Örnek
Şöyle
yaparız.
buffer.compact();
flip metodu - Okumaya Hazır Hale GetirirBu metod Java 11 ile artık Buffer yerine ByteBuffer
dönüyor. Yazma işlemi bittikten sonra okumaya hazır hale getirmek için kullanılır. Açıklaması
şöyle. flit() işlemi sonucunda limit = position yapıldığı için, okuma işleminde
buffer overrun engellenir.
When you are done putting bytes into the buffer, you should flip it.
Eğer flip() metodunu kullanmadan belleğin belli bir alanına erişmek istersek getInt(offset) gibi bir metodu kullanmak gerekir. Şöyle
yaparız,
long l = ByteBuffer.allocate(8).putInt(x).putInt(y).getLong(0);
//
ByteBuffer buffer = ByteBuffer.allocate(8).putLong(l);
x = buffer.getInt(0);
y = buffer.getInt(4);
Örnek
Şöyle yaparız.
ByteBuffer bb = ByteBuffer.allocate(1024);
... //Put data
bb.flip();
get metodu - Current position
byte okur. Şöyle yaparız. Current position ilerletilir.
ByteBuffer bb =..
byte[] b = new byte[bb.remaining()]
bb.get(b);
getFloat metodu
Şöyle
yaparız. Current position ilerletilir.
float v = ByteBuffer.wrap(...).order(ByteOrder.BIG_ENDIAN).getFloat();
getInt metodu
Bir byte[] nesnesini int değere çevirir
Örnek
byte[] digest = ...
int hash = ByteBuffer.wrap(digest).getInt();
getInt metodu - index
16. int'e erişmek için şöyle
yaparız. Current position ilerletilmez.
System.out.println(bb.getInt(16*4));
System.out.println(bb.asIntBuffer().get(16));
getShort metodu
Şöyle
yaparız. Current position ilerletilir.
ByteBuffer bb = ...;
short s = bb.getShort();
hasArray metodu
Şöyle
yaparız.
ByteBuffer bb = ...;
if (buffer.hasArray()) {
byte[] array = buffer.array();
int arrayOffset = buffer.arrayOffset();
return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
arrayOffset + buffer.limit());
}
hasRemaining metodu
Okumak veya yazmak için kullanılır.
Örnek
Sonuna kadar okumak için şöyle
yaparız.
while(buffer.hasRemaining()) {
file.write(buffer);
}
limit metodu
Açıklaması
şöyle. Belirtilen konum aşılırsa BufferOverflowException fırlatır.
mark <= position <= limit <= capacity
Örnek
Şöyle
yaparız.
ByteBuffer b= ByteBuffer.allocate(10); // capacity = 10, limit = 10
b.limit(1); //set limit to 1
b.put((byte)1);
b.put((byte)1); //causes java.nio.BufferOverflowException
order metodu
Buffer little endian olarak okunabilir.
Örnek
Şöyle
yaparız.
byte[] buf = new byte[512];
ByteBuffer bb = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN);
Örnek
Şöyle
yaparız.
ByteBuffer buf = ByteBuffer.wrap(new byte[] { (byte)0xC2, (byte)0x95, 0x3C, 0x2C,
(byte)0xC1, 0x6B, (byte)0xD6, 0x41 });
double d = buf.order(ByteOrder.LITTLE_ENDIAN).getDouble();
position metodu - getter
Şöyle
yaparız.
Arrays.copyOf(buffer.array(), 0, buffer.position());
position metodu - setter
Şöyle
yaparız.
ByteBuffer bb = ByteBuffer.allocateDirect(32);
bb.position(0);
put metodu - byte
Şöyle
yaparız.
bb.put((byte)12);
put metodu - byte []
Şöyle
yaparız. Current position ilerletilir.
bb.put("one\ntwo\nthree\nfour\n".getBytes());
put metodu- int index, byte[] src, int offset, int length
Java 16 ile geliyor. Açıklaması
şöyle
ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer and ShortBuffer all have a new put() method. These methods copy a defined length section of a second buffer, starting at a given offset in that buffer to a specified index in the buffer that the method is being called on. That description seems complicated, but it is a simple replacement for the loop:
Yani şu döngüden
kurtuluyoruzfor (int i = offset, j = index; i < offset + length; i++, j++)
destinationBuffer.put(j, sourceBuffer.get(i));
putInt metodu
Şöyle yaparız. Current position ilerletilir.
int totalPacket = ...;
bb.putInt(totalPacket);
putShort metodu
Şöyle
yaparız.
bb.putShort((short)0x03);
remaining metodu
Okumak veya yazmak için kullanılır. Geriye kalan alanı döner.
ByteBuffer bb =..
byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);
rewind metodu
position alanını 0 yapar. Yani yazma ve okuma işlemine baştan başlanabilir.
slice metodu
Bu metodun ismi bence view() olmalıydı. Açıklaması
şöyle.
The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer, and its mark will be undefined.
Açıklaması şöyle
Slicing a buffer is a slight variant of duplicating. Slicing also creates a new buffer that shares data with the old buffer. However, the slice's zero position is the current position of the original buffer, and its capacity only goes up to the source buffer's limit. That is, the slice is a subsequence of the original buffer that only contains the elements from the current position to the limit. Rewinding the slice only moves it back to the position of the original buffer when the slice was created. The slice can't see anything in the original buffer before that point.
Bu metod header + payload şeklindeki paketlerde payload kısmını ayırmak için kullanılabilir. Açıklaması şöyle
This is useful when you have a long buffer of data that is easily divided into multiple parts such as a protocol header followed by the data. You can read out the header then slice the buffer and pass the new buffer containing only the data to a separate method or class
Örnek
Şöyle
yaparız.
byte[] test = "Hello World".getBytes("Latin1");
ByteBuffer b1 = ByteBuffer.wrap(test);
byte[] hello = new byte[6];
b1.get(hello);
ByteBuffer b2 = b1.slice(); // position = 0, string = "World"
byte[] tooLong = b2.array(); // Will NOT be "World", but will be "Hello World".
byte[] world = new byte[5];
b2.get(world); // world = "World"
Örnek
Elimizdeki ByteBuffer nesnesini dst nesnesine yazmak için şöyle
yaparız.
@Override
public synchronized int read(ByteBuffer dst) {
if (buf.remaining() == 0) return -1;
int count = min(dst.remaining(), buf.remaining());
if (count > 0) {
ByteBuffer tmp = buf.slice();
tmp.limit(count);
dst.put(tmp);
buf.position(buf.position() + count);
}
return count;
}
Örnek
src ByteBuffer nesnesini elimizdeki nesneye yazmak şöyle
yaparız.
@Override
public synchronized int write(ByteBuffer src) {
if (buf.isReadOnly()) throw new NonWritableChannelException();
int count = min(src.remaining(), buf.remaining());
if (count > 0) {
ByteBuffer tmp = src.slice();
tmp.limit(count);
buf.put(tmp);
src.position(src.position() + count);
}
return count;
}
wrap metodu
Örnek - byte []
Şöyle
yaparız.
byte[] buf = new byte[512];
ByteBuffer bb = ByteBuffer.wrap(buf);
Örnek - String
Şöyle
yaparız.
ByteBuffer buffer = ByteBuffer.wrap("...".getBytes());
Socket ile Kullanım
Yazmak için şöyle
yaparız.
SocketChannel socketChannel = ...;
ByteBuffer buf = ...;
//write
while(buf.hasRemaining()) {
socketChannel.write(buf);
}
Okumak için şöyle yaparız.
//read
ByteBuffer inBuf = ByteBuffer.allocate(78);
if socketChannel.read(inBuf) > 0) {...}