在Android上,直接ByteBuffer似乎永远不会释放其内存,即使在调用System.gc()时也是如此.
示例:做
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
ByteBuffer buffer = allocateDirect(LARGE_NUMBER);
buffer=null;
System.gc();
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
Run Code Online (Sandbox Code Playgroud)
在日志中给出两个数字,第二个数字至少比第一个大LARGE_NUMBER.
我如何摆脱这种泄漏?
添加:
按照Gregory的建议来处理C++方面的alloc/free,然后我定义了
JNIEXPORT jobject JNICALL Java_com_foo_bar_allocNative(JNIEnv* env, jlong size)
{
void* buffer = malloc(size);
jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
jobject globalRef = env->NewGlobalRef(directBuffer);
return globalRef;
}
JNIEXPORT void JNICALL Java_com_foo_bar_freeNative(JNIEnv* env, jobject globalRef)
{
void *buffer = env->GetDirectBufferAddress(globalRef);
free(buffer);
env->DeleteGlobalRef(globalRef);
}
Run Code Online (Sandbox Code Playgroud)
然后我在JAVA端获得我的ByteBuffer
ByteBuffer myBuf = allocNative(LARGE_NUMBER);
Run Code Online (Sandbox Code Playgroud)
并释放它
freeNative(myBuf);
Run Code Online (Sandbox Code Playgroud)
不幸的是,虽然它确实分配好了,但它仍然保持根据Debug.getNativeHeapAllocatedSize()和b)分配的内存导致错误
W/dalvikvm(26733): JNI: DeleteGlobalRef(0x462b05a0) failed to find entry (valid=1)
Run Code Online (Sandbox Code Playgroud)
我现在彻底搞糊涂了,我以为我至少理解了C++方面的事情......为什么free()没有返回内存?我做错了DeleteGlobalRef()什么?
我在SO和其他地方看到过的每个Java循环字节缓冲区实现都没有扩展java.nio.ByteBuffer,对我来说这是与SocketChannel一起使用所必需的.有没有人知道扩展ByteBuffer的开源实现.我试着写下我自己的路,但是当我意识到位置和剩余的功能是最终的时候我被卡住了,我将覆盖那些以调整头部并防止缓冲区溢出异常.在通过套接字通道发送5000条消息时,每个人都需要我将东西复制到线性缓冲区的头部,这会增加大约450毫秒或90us的每条消息(其中包含10个数据包,因此每个数据包为9us).现在,我能想到的唯一方法是覆盖每一个方法并重写所有方法.有任何想法吗?
有天赋的人可以用简单直接的方式解释复杂的事情来解决这个问题吗?要在使用Java NIO进行网络I/O时,何时使用直接ByteBuffers与常规ByteBuffers,以获得最佳性能?
例如:我应该读入堆缓冲区并从那里解析它,执行许多get()(逐字节)或者我应该将它读入直接缓冲区并从直接缓冲区解析?
我最近遇到了sun.misc.Unsafe类,允许用户以类似于C的方式分配,解除分配和一般访问内存.我在几个博客中读到了解决这个问题,例如
MappedByteBuffer比堆对象更快第1条似乎与其他条款相矛盾,我无法理解其中的原因.DirectMemoryBuffer正在底层使用sun.misc.Unsafe(所以MappedByteBuffer),因此它们也应该受到第1条所述的JNI调用的困扰.另外,在第2条中,堆外内存访问类似于第1条中的内容,并给出完全相反的结果.
有人可以评论如何处理堆外记忆,即何时使用它,是否有显着的好处,最重要的是,为什么类似的主题根据上述文章给出了截然不同的结果?谢谢.
如何将两个ByteBuffers连接到一个ByteBuffer?
以下不起作用:
ByteBuffer bb = ByteBuffer.allocate(100);
ByteBuffer bb2 = ByteBuffer.allocate(200);
bb.allocate(200).put(bb2);
System.out.println(bb.array().length);
Run Code Online (Sandbox Code Playgroud)
长度bb仍然是100.
如何从只读的ByteBuffer中提取String?我不能使用ByteBuffer.array()方法,因为它会抛出ReadOnlyException.我是否必须使用ByteBuffer.get(arr [])并将其复制出来以读取数据并创建字符串?似乎浪费了必须创建一个副本只是为了阅读它.
如何获得指向Java ByteBuffer内部数组的指针?
JNIEXPORT void JNICALL test(JNIEnv *env, jobject thiso) {
jclass cls = env->FindClass("java/nio/ByteBuffer");
jmethodID aloc = env->GetStaticMethodID(cls, "allocateDirect", "(I)Ljava/nio/ByteBuffer;");
jobject obj = env->CallStaticObjectMethod(cls, aloc, 1000);
}
Run Code Online (Sandbox Code Playgroud)
PS:我这样做是为了分享Java和C++使用的内存.
我需要一个类似于Java的ByteBuffer的C#实现.感兴趣的方法 - .remaining() - 返回当前位置和限制之间的元素数量. - .array() - .clear() - .put(byte [],int,int)
我开始用MemoryStream...但是没有clear(),还有很多即兴创作此外,我在Koders上找到了ac#implementation:http://www.koders.com/csharp/fid2F8CB1B540E646746D3ADCB2B0AC867A0A8DCB06.aspx? s=socket#L2 ..我会使用..但也许你们知道更好的东西
我在Android项目中使用JNI代码,其中JNI本机函数需要short []参数.但是,原始数据存储为ByteBuffer.我正在尝试转换数据格式如下.
ByteBuffer rgbBuf = ByteBuffer.allocate(size);
...
short[] shortArray = (short[]) rgbBuf.asShortBuffer().array().clone();
Run Code Online (Sandbox Code Playgroud)
但是在运行上面显示的第二行代码时遇到以下问题:
E/AndroidRuntime(23923): Caused by: java.lang.UnsupportedOperationException
E/AndroidRuntime(23923): at Java.nio.ShortToByteBufferAdapter.protectedArray(ShortToByteBufferAdapter.java:169)
Run Code Online (Sandbox Code Playgroud)
任何人都可以提出实施转换的方法吗?
我有一堆键和值,我想通过将它们打包到一个字节数组中发送到我们的消息队列.我将创建所有键和值的一个字节数组,该数组应始终小于50K,然后发送到我们的消息队列.
包类:
public final class Packet implements Closeable {
private static final int MAX_SIZE = 50000;
private static final int HEADER_SIZE = 36;
private final byte dataCenter;
private final byte recordVersion;
private final long address;
private final long addressFrom;
private final long addressOrigin;
private final byte recordsPartition;
private final byte replicated;
private final ByteBuffer itemBuffer = ByteBuffer.allocate(MAX_SIZE);
private int pendingItems = 0;
public Packet(final RecordPartition recordPartition) {
this.recordsPartition = (byte) recordPartition.getPartition();
this.dataCenter = Utils.LOCATION.get().datacenter();
this.recordVersion = 1;
this.replicated = …Run Code Online (Sandbox Code Playgroud) java oop design-patterns bytebuffer single-responsibility-principle
bytebuffer ×10
java ×8
android ×2
android-ndk ×1
buffer ×1
c# ×1
c++ ×1
heap ×1
memory-leaks ×1
nio ×1
oop ×1
real-time ×1