title: Why is DoubleBuffer.put() allocating memory, and how should I avoid this happening?
body: <p>In my Android app, I have a loop in a thread that does some processing of data stored in <code>DoubleBuffer</code> objects. To my surprise, <a href="https://developer.android.com/reference/java/nio/DoubleBuffer.html#put(java.nio.DoubleBuffer)" rel="nofollow noreferrer"><code>put(DoubleBuffer)</code></a> appears to be allocating memory!</p>
  
  <p>Is this something I should have expected? To me, it seems to go against everything I thought I understood about NIO buffers. Is there something I should be doing to avoid it?</p>
  
  <p>I'm able to reproduce this with a minimal example that simply copies between two buffers in a loop. Run via Android Studio on a physical phone running Android 4.4.2, the log is filled with lines like the following:</p>
  
  <blockquote>
  <pre><code>D/dalvikvm: GC_FOR_ALLOC freed 2032K, 55% free 6556K/14500K, paused 11ms, total 11ms
  </code></pre>
  </blockquote>
  
  <p>If I comment out the call to <code>put()</code>, this does not happen.</p>
  
  <p>Here's the code I reproduced this issue with, written on top of the "empty activity" template:</p>
  
  <pre><code>public class MainActivity extends AppCompatActivity {
      private Thread thread;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
      }
  
      @Override
      protected void onStart() {
          super.onStart();
          thread = new Thread(new Runnable() {
              @Override
              public void run() {
                  DoubleBuffer buffer1 = DoubleBuffer.allocate(5000);
                  DoubleBuffer buffer2 = DoubleBuffer.allocate(buffer1.capacity());
                  while (!Thread.interrupted()) {
                      // set remaining to capacity so that entire buffer is copied
                      buffer1.clear();
                      buffer2.clear();
                      buffer2.put(buffer1);
                      Thread.yield();
                  }
              }
          });
          thread.setDaemon(true);
          thread.start();
      }
  
      @Override
      protected void onStop() {
          if (thread != null) {
              thread.interrupt();
              thread = null;
          }
          super.onStop();
      }
  }
  </code></pre>
  
  <p>And here's the relevant parts of <code>app/build.gradle</code>:</p>
  
  <pre><code>apply plugin: 'com.android.application'
  
  android {
      compileSdkVersion 25
      buildToolsVersion "25.0.2"
      defaultConfig {
          minSdkVersion 10
          targetSdkVersion 25
      }
  }
  
  dependencies {
      compile 'com.android.support:appcompat-v7:25.1.0'
  }
  </code></pre>