blob: 59e5b5e4ac950562980a5374eead9c4ad9324f2f [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<title>Chapter 8 - IoBuffer &mdash; Apache MINA</title>
<link href="/assets/css/common.css" rel="stylesheet" type="text/css"/>
<link href="/assets/css/mina.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<script src="https://www.apachecon.com/event-images/snippet.js"></script>
<div id="container">
<div id="header">
<div id="subProjectsNavBar">
<a href="/">
Apache MINA Project
</a>
&nbsp;|&nbsp;
<a href="/mina-project/">
<strong>MINA</strong>
</a>
&nbsp;|&nbsp;
<a href="/asyncweb-project/">
AsyncWeb
</a>
&nbsp;|&nbsp;
<a href="/ftpserver-project/">
FtpServer
</a>
&nbsp;|&nbsp;
<a href="/sshd-project/">
SSHD
</a>
&nbsp;|&nbsp;
<a href="/vysper-project/">
Vysper
</a>
</div>
</div>
<div id="content">
<div id="leftColumn">
<div id="navigation">
<a class="acevent" data-format="wide" data-width="170"></a>
<h5>Social Networks</h5>
<ul>
<li><a href="https://fosstodon.org/@apachemina">Apache MINA Mastodon</a></li>
</ul>
<h5>Latest Downloads</h5>
<ul>
<li><a href="/mina-project/downloads_2_0.html">Mina 2.0.25</a></li>
<li><a href="/mina-project/downloads_2_1.html">Mina 2.1.8</a></li>
<li><a href="/mina-project/downloads_2_2.html">Mina 2.2.3</a></li>
<li><a href="/mina-project/downloads_old.html">Mina old versions</a></li>
</ul>
<h5>Documentation</h5>
<ul>
<li><a href="/mina-project/documentation.html" class="external-link" rel="nofollow">Base documentation</a></li>
<li><a href="/mina-project/userguide/user-guide-toc.html" class="external-link" rel="nofollow">User guide</a></li>
<li><a href="/mina-project/2.2-vs-2.1.html" class="external-link" rel="nofollow">2.2 vs 2.1</a></li>
<li><a href="/mina-project/2.1-vs-2.0.html" class="external-link" rel="nofollow">2.1 vs 2.0</a></li>
<li><a href="/mina-project/features.html" class="external-link" rel="nofollow">Features</a></li>
<li><a href="/mina-project/road-map.html" class="external-link" rel="nofollow">Road Map</a></li>
<li><a href="/mina-project/quick-start-guide.html" class="external-link" rel="nofollow">Quick Start Guide</a></li>
<li><a href="/mina-project/faq.html" class="external-link" rel="nofollow">FAQ</a></li>
</ul>
<h5>Resources</h5>
<ul>
<li><a href="/mina-project/mailing-lists.html" class="external-link" rel="nofollow">Mailing lists &amp; IRC</a></li>
<li><a href="/mina-project/issue-tracking.html" class="external-link" rel="nofollow">Issue tracking</a></li>
<li><a href="/mina-project/sources.html" class="external-link" rel="nofollow">Sources</a></li>
<li><a href="/mina-project/gen-docs/latest-2.0/apidocs/index.html" class="external-link" rel="nofollow">API Javadoc 2.0.25</a></li>
<li><a href="/mina-project/gen-docs/latest-2.1/apidocs/index.html" class="external-link" rel="nofollow">API Javadoc 2.1.8</a></li>
<li><a href="/mina-project/gen-docs/latest-2.2/apidocs/index.html" class="external-link" rel="nofollow">API Javadoc 2.2.3</a></li>
<li><a href="/mina-project/gen-docs/latest-2.0/xref/index.html" class="external-link" rel="nofollow">API xref 2.0.25</a></li>
<li><a href="/mina-project/gen-docs/latest-2.1/xref/index.html" class="external-link" rel="nofollow">API xref 2.1.8</a></li>
<li><a href="/mina-project/gen-docs/latest-2.2/xref/index.html" class="external-link" rel="nofollow">API xref 2.2.3</a></li>
<li><a href="/mina-project/performances.html" class="external-link" rel="nofollow">Performances</a></li>
<li><a href="/mina-project/testimonials.html" class="external-link" rel="nofollow">Testimonials</a></li>
<li><a href="/mina-project/conferences.html" class="external-link" rel="nofollow">Conferences</a></li>
<li><a href="/mina-project/developer-guide.html" class="external-link" rel="nofollow">Developers Guide</a></li>
<li><a href="/mina-project/related-projects.html" class="external-link" rel="nofollow">Related Projects</a></li>
<li><a href="https://people.apache.org/~vgritsenko/stats/projects/mina.html" class="external-link" rel="nofollow">Statistics</a></li>
</ul>
<h5>Community</h5>
<ul>
<li><a href="https://www.apache.org/foundation/contributing.html" class="external-link" rel="nofollow">Contributing</a></li>
<li><a href="/contributors.html" class="external-link" rel="nofollow">Team</a></li>
<li><a href="/special-thanks.html" class="external-link" rel="nofollow">Special Thanks</a></li>
<li><a href="https://www.apache.org/security/" class="external-link" rel="nofollow">Security</a></li>
</ul>
<h5>About Apache</h5>
<ul>
<li><a href="https://www.apache.org" class="external-link" rel="nofollow">Apache main site</a></li>
<li><a href="https://www.apache.org/licenses/" class="external-link" rel="nofollow">License</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html" title="The ASF sponsorship program" class="external-link" rel="nofollow">Sponsorship program</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html" class="external-link" rel="nofollow">Thanks</a></li>
</ul>
<h3><a name="Navigation-Upcoming"></a>Upcoming</h3>
<ul>
<li>No event</li>
</ul>
</div>
</div>
<div id="rightColumn">
<div class="nav">
<div class="nav_prev">
<a href="../ch7-handler/ch7-handler.html">Chapter 7 - IoHandler</a>
</div>
<div class="nav_up">
<a href="../user-guide-toc.html">User Guide</a>
</div>
<div class="nav_next">
<a href="../ch9-codec-filter/ch9-codec-filter.html">Chapter 9 - Codec Filter</a>
</div>
<div class="clearfix"></div>
</div>
<h1 id="chapter-8---iobuffer">Chapter 8 - IoBuffer</h1>
<p>A byte buffer used by MINA applications.</p>
<p>This is a replacement for <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/nio/ByteBuffer.html">ByteBuffer</a>. MINA does not use NIO ByteBuffer directly for two reasons:</p>
<ul>
<li>It doesn&rsquo;t provide useful getters and putters such as fill, get/putString, and get/putAsciiInt() .</li>
<li>It is difficult to write variable-length data due to its fixed capacity</li>
</ul>
<div class="note" markdown="1">
This will change in MINA 3. The main reason why MINA has its own wrapper on top of nio ByteBuffer is to have extensible buffers. This was a very bad decision. Buffers are just buffers : a temporary place to store temporary data, before it is used. Many other solutions exist, like defining a wrapper which relies on a list of NIO ByteBuffers, instead of copying the existing buffer to a bigger one just because we want to extend the buffer capacity.
<p>It might also be more comfortable to use an InputStream instead of a byte buffer all along the filters, as it does not imply anything about the nature of the stored data : it can be a byte array, strings, messages...</p>
<p>Last, not least, the current implementation defeat one of the target : zero-copy strategy (ie, once we have read the data from the socket, we want to avoid a copy being done later). As we use extensible byte buffers, we will most certainly copy those data if we have to manage big messages. Assuming that the MINA ByteBuffer is just a wrapper on top of NIO ByteBuffer, this can be a real problem when using direct buffers.</p>
</div>
<h2 id="iobuffer-operations">IoBuffer Operations</h2>
<h3 id="allocating-a-new-buffer">Allocating a new Buffer</h3>
<p>IoBuffer is an abstract class, hence can&rsquo;t be instantiated directly. To allocate IoBuffer, we need to use one of the two allocate() methods.</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#080;font-style:italic">// Allocates a new buffer with a specific size, defining its type (direct or heap)
</span><span style="color:#080;font-style:italic"></span><span style="color:#a2f;font-weight:bold">public</span> <span style="color:#a2f;font-weight:bold">static</span> IoBuffer <span style="color:#00a000">allocate</span><span style="color:#666">(</span><span style="color:#0b0;font-weight:bold">int</span> capacity<span style="color:#666">,</span> <span style="color:#0b0;font-weight:bold">boolean</span> direct<span style="color:#666">)</span>
<span style="color:#080;font-style:italic">// Allocates a new buffer with a specific size
</span><span style="color:#080;font-style:italic"></span><span style="color:#a2f;font-weight:bold">public</span> <span style="color:#a2f;font-weight:bold">static</span> IoBuffer <span style="color:#00a000">allocate</span><span style="color:#666">(</span><span style="color:#0b0;font-weight:bold">int</span> capacity<span style="color:#666">)</span>
</code></pre></div><p>The allocate() method takes one or two arguments. The first form takes two arguments :</p>
<ul>
<li><strong>capacity</strong> - the capacity of the buffer</li>
<li><strong>direct</strong> - type of buffer. true to get direct buffer, false to get heap buffer</li>
</ul>
<p>The default buffer allocation is handled by <a href="https://nightlies.apache.org/mina/mina/2.0.22/xref/org/apache/mina/core/buffer/SimpleBufferAllocator.html">SimpleBufferAllocator</a></p>
<p>Alternatively, following form can also be used</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#080;font-style:italic">// Allocates heap buffer by default.
</span><span style="color:#080;font-style:italic"></span>IoBuffer<span style="color:#666">.</span><span style="color:#b44">setUseDirectBuffer</span><span style="color:#666">(</span><span style="color:#a2f;font-weight:bold">false</span><span style="color:#666">)</span><span style="color:#666">;</span>
<span style="color:#080;font-style:italic">// A new heap buffer is returned.
</span><span style="color:#080;font-style:italic"></span>IoBuffer buf <span style="color:#666">=</span> IoBuffer<span style="color:#666">.</span><span style="color:#b44">allocate</span><span style="color:#666">(</span>1024<span style="color:#666">)</span><span style="color:#666">;</span>
</code></pre></div><p>When using the second form, don&rsquo;t forget to set the default buffer type before, otherwise you will get Heap buffers by default.</p>
<h2 id="creating-auto-expanding-buffer">Creating Auto Expanding Buffer</h2>
<p>Creating auto expanding buffer is not very easy with java NIO API&rsquo;s, because of the fixed size of the buffers. Having a buffer, that can auto expand on needs is a big plus for networking applications. To address this, IoBuffer has introduced the autoExpand property. It automatically expands its capacity and limit value.</p>
<p>Lets see how to create an auto expanding buffer :</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">IoBuffer buffer <span style="color:#666">=</span> IoBuffer<span style="color:#666">.</span><span style="color:#b44">allocate</span><span style="color:#666">(</span>8<span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">setAutoExpand</span><span style="color:#666">(</span><span style="color:#a2f;font-weight:bold">true</span><span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">putString</span><span style="color:#666">(</span><span style="color:#b44">&#34;12345678&#34;</span><span style="color:#666">,</span> encoder<span style="color:#666">)</span><span style="color:#666">;</span>
<span style="color:#080;font-style:italic">// Add more to this buffer
</span><span style="color:#080;font-style:italic"></span>buffer<span style="color:#666">.</span><span style="color:#b44">put</span><span style="color:#666">(</span><span style="color:#666">(</span><span style="color:#0b0;font-weight:bold">byte</span><span style="color:#666">)</span>10<span style="color:#666">)</span><span style="color:#666">;</span>
</code></pre></div><p>The underlying ByteBuffer is reallocated by IoBuffer behind the scene if the encoded data is larger than 8 bytes in the example above. Its capacity will double, and its limit will increase to the last position the string is written. This behavior is very similar to the way StringBuffer class works.</p>
<div class="note" markdown="1">
This mechanism is very likely to be removed from MINA 3.0, as it's not really the best way to handle increased buffer size. It should be replaced by something like a InputStream hiding a list or an array of fixed sized ByteBuffers.
</div>
<h2 id="creating-auto-shrinking-buffer">Creating Auto Shrinking Buffer</h2>
<p>There are situations which calls for releasing additionally allocated bytes from the buffer, to preserve memory. IoBuffer provides autoShrink property to address the need. If autoShrink is turned on, IoBuffer halves the capacity of the buffer when compact() is invoked and only 1/4 or less of the current capacity is being used. To manually shrink the buffer, use shrink() method.</p>
<p>Lets see this in action :</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">IoBuffer buffer <span style="color:#666">=</span> IoBuffer<span style="color:#666">.</span><span style="color:#b44">allocate</span><span style="color:#666">(</span>16<span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">setAutoShrink</span><span style="color:#666">(</span><span style="color:#a2f;font-weight:bold">true</span><span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">put</span><span style="color:#666">(</span><span style="color:#666">(</span><span style="color:#0b0;font-weight:bold">byte</span><span style="color:#666">)</span>1<span style="color:#666">)</span><span style="color:#666">;</span>
System<span style="color:#666">.</span><span style="color:#b44">out</span><span style="color:#666">.</span><span style="color:#b44">println</span><span style="color:#666">(</span><span style="color:#b44">&#34;Initial Buffer capacity = &#34;</span><span style="color:#666">+</span>buffer<span style="color:#666">.</span><span style="color:#b44">capacity</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">shrink</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">;</span>
System<span style="color:#666">.</span><span style="color:#b44">out</span><span style="color:#666">.</span><span style="color:#b44">println</span><span style="color:#666">(</span><span style="color:#b44">&#34;Initial Buffer capacity after shrink = &#34;</span><span style="color:#666">+</span>buffer<span style="color:#666">.</span><span style="color:#b44">capacity</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">capacity</span><span style="color:#666">(</span>32<span style="color:#666">)</span><span style="color:#666">;</span>
System<span style="color:#666">.</span><span style="color:#b44">out</span><span style="color:#666">.</span><span style="color:#b44">println</span><span style="color:#666">(</span><span style="color:#b44">&#34;Buffer capacity after incrementing capacity to 32 = &#34;</span><span style="color:#666">+</span>buffer<span style="color:#666">.</span><span style="color:#b44">capacity</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">)</span><span style="color:#666">;</span>
buffer<span style="color:#666">.</span><span style="color:#b44">shrink</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">;</span>
System<span style="color:#666">.</span><span style="color:#b44">out</span><span style="color:#666">.</span><span style="color:#b44">println</span><span style="color:#666">(</span><span style="color:#b44">&#34;Buffer capacity after shrink= &#34;</span><span style="color:#666">+</span>buffer<span style="color:#666">.</span><span style="color:#b44">capacity</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">)</span><span style="color:#666">;</span>
</code></pre></div><p>We have initially allocated a capacity as 16, and set the autoShrink property as true.</p>
<p>Lets see the output of this :</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">Initial Buffer capacity <span style="color:#666">=</span> 16
Initial Buffer capacity after shrink <span style="color:#666">=</span> 16
Buffer capacity after incrementing capacity to 32 <span style="color:#666">=</span> 32
Buffer capacity after shrink<span style="color:#666">=</span> 16
</code></pre></div><p>Lets take a break and analyze the output</p>
<ul>
<li>Initial buffer capacity is 16, as we created the buffer with this capacity. Internally this becomes the minimum capacity of the buffer</li>
<li>After calling shrink(), the capacity remains 16, as capacity shall never be less than minimum capacity</li>
<li>After incrementing capacity to 32, the capacity becomes 32</li>
<li>Call to shrink(), reduces the capacity to 16, thereby eliminating extra storage</li>
</ul>
<div class="note" markdown="1">
Again, this mechanism should be a default one, without needing to explicitely tells the buffer that it can shrink.
</div>
<h2 id="buffer-allocation">Buffer Allocation</h2>
<p>IoBufferAllocator is responsible for allocating and managing buffers. To have precise control on the buffer allocation policy, implement the IoBufferAllocator interface.</p>
<p>MINA ships with following implementations of IoBufferAllocator</p>
<ul>
<li><strong>SimpleBufferAllocator (default)</strong> - Create a new buffer every time</li>
<li><strong>CachedBufferAllocator</strong> - caches the buffer which are likely to be reused during expansion</li>
</ul>
<div class="note" markdown="1">
With the new available JVM, using cached IoBuffer is very unlikely to improve performances.
</div>
<p>You can implement you own implementation of IoBufferAllocator and call setAllocator() on IoBuffer to use the same.</p>
<div class="nav">
<div class="nav_prev">
<a href="../ch7-handler/ch7-handler.html">Chapter 7 - IoHandler</a>
</div>
<div class="nav_up">
<a href="../user-guide-toc.html">User Guide</a>
</div>
<div class="nav_next">
<a href="../ch9-codec-filter/ch9-codec-filter.html">Chapter 9 - Codec Filter</a>
</div>
<div class="clearfix"></div>
</div>
</div>
<div id="endContent"></div>
</div>
<div id="footer">
&copy; 2003-2024, <a href="https://www.apache.org">The Apache Software Foundation</a> - <a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a><br />
Apache MINA, MINA, Apache Vysper, Vysper, Apache SSHd, SSHd, Apache FtpServer, FtpServer, Apache AsyncWeb, AsyncWeb,
Apache, the Apache feather logo, and the Apache Mina project logos are trademarks of The Apache Software Foundation.
</div>
</div>
</body>
</html>