请问Android如何释放ByteBuffer.allocateDirect申请的内存

apu-perf 2017-09-01 04:13:29
我在制作一个3D测试应用的时候遇到一个问题,这是一个地球3D模型应用,使用ByteBuffer.allocateDirect申请堆外内存,反复多次进出该应用之后,就会出现OOM现象。在网上查了很多关于ByteBuffer.allocateDirect的资料,没有找到解决办法,请教下高手如何解决?

申请内存:
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置

释放:
1、第一种说法是触发full gc就会回收,但是每次进入和退出应用都调用System.gc()没有起作用,资料说jvm的堆外内存无法通过System.gc()释放。所以这种方法我没试验成功。
2、第二种说法:import sun.nio.ch.DirectBuffer ,((DirectBuffer)vbb).cleaner().clean(),但是找不到sun.nio.ch.DirectBuffer 这个类,无法import。
3、第三种说法是反射机制,但是运行时发现getMethod("cleaner")的cleaner找不到出错
   Method cleanerMethod = buffer.getClass().getMethod("cleaner");
   cleanerMethod.setAccessible(true);
   Object cleaner = cleanerMethod.invoke(buffer);
   Method cleanMethod = cleaner.getClass().getMethod("clean");
   cleanMethod.setAccessible(true);
   cleanMethod.invoke(cleaner);

AndroidRuntime Exception:
09-01 15:46:46.212 29144 5690 E AndroidRuntime: FATAL EXCEPTION: GLThread 7970
09-01 15:46:46.212 29144 5690 E AndroidRuntime: Process: com.test.earth, PID: 29144
09-01 15:46:46.212 29144 5690 E AndroidRuntime: java.lang.OutOfMemoryError: Failed to allocate a 3110412 byte allocatio
n with 1374136 free bytes and 1341KB until OOM
09-01 15:46:46.212 29144 5690 E AndroidRuntime: at com.test.earth.component.TestActivity$Ball.<init>(TestActivity.java:562)
09-01 15:46:46.212 29144 5690 E AndroidRuntime: at com.test.earth.component.TestActivity$SceneRenderer.
onSurfaceCreated(TestActivity.java:273)
09-01 15:46:46.212 29144 5690 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
09-01 15:46:46.212 29144 5690 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:
1259)
...全文
1660 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_36419471 2021-01-18
  • 打赏
  • 举报
回复
最后咋解决了
apu-perf 2017-09-04
  • 打赏
  • 举报
回复
我搜索到http://blog.csdn.net/aitangyong/article/details/39323125文章里说ByteBuffer.allocateDirect系统会自动释放内存,我按照文章里做了个死循环申请内存,打印结果确实是堆外内存没有增加。 这就尴尬了,我的3D代码难道会是“除非堆内存中的ByteBuffer对象由于错误编码而出现内存泄露”?那似乎可以找到问题根本原因,就不用纠结上述的问题了。可惜博主精彩的文章戛然而止,未能够寻找到为何会因为错误编码导致内存泄露,还望各位高手不吝指教,谢谢! 1、首先我们看下NIO中提供的ByteBuffer import java.nio.ByteBuffer;      public class TestDirectByteBuffer   {       // -verbose:gc -XX:+PrintGCDetails -XX:MaxDirectMemorySize=40M       public static void main(String[] args) throws Exception       {           while (true)           {               ByteBuffer buffer = ByteBuffer.allocateDirect(10 * 1024 * 1024);           }       }   }   我们将最大堆外内存设置成40M,运行这段代码会发现:程序可以一直运行下去,不会报OutOfMemoryError。如果使用了-verbose:gc -XX:+PrintGCDetails,会发现程序频繁的进行垃圾回收活动。于是我们可以得出结论:ByteBuffer.allocateDirect分配的堆外内存不需要我们手动释放,而且ByteBuffer中也没有提供手动释放的API。也即是说,使用ByteBuffer不用担心堆外内存的释放问题,除非堆内存中的ByteBuffer对象由于错误编码而出现内存泄露。

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧