The message buffer described by class Buffer is used for explicit packing and unpacking of messages. The sender creates a communication buffer object of type Buffer. Internally this buffer maintains a vector of bytes reflecting the wire format of the message.
This class is a base class for several concrete classes described below. Constructors for those classes specify a fixed initial capacity. The effective public interface of the Buffer class itself is given in Figure 5.2. We can increase the buffer capacity by calling ensureCapacity(). This method will temporarily increase capacity to newCapacity for extra space and will clear previous data from the buffer. The method restoreCapacity() is called after to one or more calls to ensureCapacity(). It restores the buffer capacity to its original value and frees extra storage that was temporarily allocated. It also clears data from the buffer. The method free() is used to free the Buffer object. This method is important for implementations of Buffer based on native methods. In those implementations, the message vector may be maintained as a dynamically allocated C array that needs an explicit free() call to recover its storage. In pure-Java implementations this job will be done by the Java garbage collector--calling free() is optional. The constant SECTION_OVERHEAD defines some extra space needed on each message section. This will be explained in depth in section 5.3.
The Buffer class has two subclasses for primitive-type data: WriteBuffer for packing and ReadBuffer for unpacking. Packing and unpacking of messages that include Object types is handled by two special subclasses of WriteBuffer and ReadBuffer: ObjectWriteBuffer and ObjectReadBuffer.
The effective public interface of the WriteBuffer and ReadBuffer classes are represented in Figure 5.3 and Figure 5.4. When constructors WriteBuffer() or ReadBuffer() create an object they allocate a message vector with size of capacity. The write(), gather(), and strGather() are used for packing data. The read(), scatter(), and strScatter() are used for unpacking data. In Figure 5.3, the symbol runs over all Java primitive types--e.g. there are actually 8 different write() methods corresponding to the 8 different primitive types in Java. Each class has three main kinds of method to deal with contiguous and non-contiguous data. Two of those pack and unpack methods (read() and write()) deal with a contiguous data and the other four (gather(), strGather(), scatter(), and strScatter()) deal with non-contiguous data.
In the WriteBuffer class, we can make write buffer vector empty using clear() method. Any later data is then stored from the beginning of vector. The programmer can re-read a vector from the start by calling method reset() in the ReadBuffer class.
To support object serialization technology for the Java Object type, we need more functionalities. Two special classes, ObjectWriteBuffer (Figure 5.5) and ObjectReadBuffer (Figure 5.6), have additional pack and unpack methods for Object arrays. Notice these classes also inherit methods for primitive types. This allows to store Object type with primitive types in the buffer vector. These classes store serialized data into the separate Java byte  array. Overridden clear() and free() methods do some extra work for dealing with the serialized byte array. Both methods flush and close a serialization stream. For clear() it will deallocate the stream object. The programmer must call the flush() method before sending the message. It prepares the byte array with the serialized Java objects, ready for sending.