title: JNI - Free ByteBuffer from C++
body: <p><strong>Summary</strong></p>
  
  <ol>
  <li>Create ByteBuffer in Java called buffer with ByteBuffer.allocateDirect(someBufferSize)</li>
  <li>Fill buffer with data</li>
  <li>Pass buffer to C++ as jobject - jbuffer</li>
  <li>Get buffer direct pointer with env->GetDirectBufferAddress(jbuffer)</li>
  <li>Work with buffer data on C++ side. How prevent GC to cleanup our buffer or it will never happen?</li>
  <li>Work done - we don't need jbuffer now.</li>
  <li>Release jbuffer? free(jbuffer) - will raise an invalid address error</li>
  </ol>
  
  <p><strong>Long part</strong></p>
  
  <p>I use next code to load PNG files with Java AssetManager to use them for Open GL ES 2.0 textures creation.</p>
  
  <p><strong>Java side PNG class</strong></p>
  
  <pre><code>import java.nio.ByteBuffer;
  import android.graphics.Bitmap;
  
  public class PNG 
  {
   private static final int BYTES_PER_PIXEL_PNG = 4;
   private static final String LOG_TAG = "[PNG]";
   public int width;
   public int height;
   public ByteBuffer pixels;
  
  
   public PNG(Bitmap bitmap)
   {
    this.width = bitmap.getWidth();
    this.height = bitmap.getHeight();
    this.pixels = ByteBuffer.allocateDirect(this.width * this.height * BYTES_PER_PIXEL_PNG);
    bitmap.copyPixelsToBuffer(this.pixels);
   }
  }
  
  public static PNG loadPNG(String path)
  {
      InputStream is = null;
      try
      {
          is = ASSETS_MANAGER.open(path);//get png file stream with AssetsManager instance
      }
      catch (IOException e)
      {
          Log.e(LOG_TAG, "Can't load png - " + path, e);
      }
  
      return new PNG(BitmapFactory.decodeStream(is));
  }
  </code></pre>
  
  <p><strong>C++ side PNG</strong></p>
  
  <pre><code>typedef struct png
  {
  int width;
  int height;
  char* pixels;
  } png;
  
  png* load_png(const char* path)
  {
   png* res = (res*) malloc(sizeof(png);
   ...
   jobject _png = env-&gt;CallStaticObjectMethod(get_java_lib_class(), get_method_id(JAVA_LIB_LOAD_PNG, JAVA_LIB_LOAD_PNG_SIGN), _path);//Calling loadPng() from Java, get PNG jobject
   jobject _pixels =  env-&gt;GetObjectField(_png, PNG_FIELDS-&gt;PNG_PIXELS_ID);//Getting pixels field from Java PNG jobject
   res-&gt;pixels = (char*) env-&gt;GetDirectBufferAddress(_pixels);//Get direct pointer to our pixel data
   //Cleanup
   ...
   env-&gt;DeleteLocalRef(_png);
   env-&gt;DeleteLocalRef(_pixels);
   return res;
  }
  </code></pre>
  
  <p><strong>Then using png to create texture</strong></p>
  
  <pre><code>void test_create_tex(const char* path)
  {
   ...
   png* source = load_png(path);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source-&gt;width, source-&gt;height, 0, GL_RGBA, GL_UNSIGNED_BYTE, source-&gt;pixels);
  //We don't need source pixel data any more
  //free(source-&gt;pixels);//INVALID HEAP ADDRESS (deadbaad)
  free(source);
  }
  </code></pre>
  
  <p>So how release byte buffer after using in C++ side with it's direct pointer? It is allocate directly (like malloc - on native side) and must be freed or i will get OutOfMemory error.</p>