苹果6splus怎么提取蜜芽宝贝签到现金

Android在JNI中使用ByteBuffer的方法
作者:沧海一粟……
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Android在JNI中使用ByteBuffer的方法,涉及Android中缓冲区的相关使用技巧,需要的朋友可以参考下
本文实例讲述了Android在JNI中使用ByteBuffer的方法。分享给大家供大家参考。具体如下:
一、ByteBuffer 定义
在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区)
缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型。ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer。
ByteBuffer有以下几种常见属性:
mark:初始值为-1,标记索引地点;
position:初始值为0,索引下标;
limit:最好定义成bytebuffer的长度,即允许可读空间长度;
capacity:缓冲区能容纳的数据元素的最大数量,创建之后无法被改变;
二、ByteBuffer使用
1. 创建ByteBuffer
① 使用allocate()创建:
ByteBuffer buf = ByteBuffer.allocate(length);
//length表示buf的长度
② 使用数组创建:
ByteBuffer buf = ByteBuffer.wrap(byteArray);
//byteArray表示一个数组
2. 回绕缓冲区
buf.flip();
这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头而不是末尾开始.回绕保持缓冲区中的数据不变,只是准备写入而不是读取。
3. 清除缓冲区
buf.clear();
这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值.不必为了每次读写都创建新的缓冲区,那样做会降低性能.相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区。
4. ByteBuffer与byte[]交互
byte[] bytearray = new byte[10];
ByteBuffer buf = ByteBuffer.wrap(bytearray);
//将数组写入buf
bytearray = new byte[buf.remaining()];
buf.get(bytearray,0,bytearray.length());
//将数据读到数组中
bytearray = new byte[buf.capacity()];
三、ByteBuffer与JNI交互
在Java1.4版本中引入的JNI有三个函数可以用于NIO的直接缓冲器。一个直接字节缓冲器是一个用于字节数据的容器,Java将尽力在它上面执行本机I/O操作。JNI定义了三个用于NIO操作的函数。
基于到存储器地址的指针以及存储器长度(容量),函数分配并且返回一个新的Java.nio.ByteBuffer。如果函数没有针对当前Java虚拟机实现,则返回NULL,或者抛出一个异常。如果没有存储器可用,则将会抛出一个OutOfMemoryException。
jobject NewDirectByteBuffer(void* address, jlong capacity);
GetDirectBufferAddress函数返回一个指向被传入的java.nio.ByteBuffer对象的地址指针。如果函数尚未针对当前虚拟机实现,或者如果buf不是java.nio.ByteBuffer的一个对象,又或者存储器区尚未定义,则都将返回NULL。
void* GetDirectBufferAddress(jobject buf);
GetDirectBufferCapacity函数返回被传入的java.nio.ByteBuffer对象的容量(以字节计数)。如果函数没有针对当前环境实现,或者如果buf不是java.nio.ByteBuffer类型的对象返回-1。
jlong GetDirectBufferCapacity(jobject buf);
1. Jni中调用
public final int processData(ByteBuffer data);
Native 接口:
private native long native_Process(ByteBuffer data);
static jlong native_Process(JNIEnv *env,jobject obj,jobject data);
注意ByteBuffer在JNI层中的签名:Ljava/nio/ByteB
2. 示例(C++):
jclass cls = env-&GetObjectClass(obj);
jfieldID fid = env-&GetFieldID(cls, "data","Ljava/nio/ByteB");
jobject bar = env-&GetObjectField(obj, fid);
pImageData-&data= (MByte*)env-&GetDirectBufferAddress(bar);
//data是结构体pImageData中的byte[];
希望本文所述对大家的Android程序设计有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具下次自動登錄
現在的位置:
& 綜合 & 正文
java之HeapByteBuffer&DirectByteBuffer以及回收DirectByteBuffer
byte buffer一般在網路交互過程中java使用得比較多,尤其是以NIO的框架中;
看名字就知道是以位元組碼作為緩衝的,先buffer一段,然後flush到終端。
而本文要說的一個重點就是HeapByteBuffer與DirectByteBuffer,以及如何合理使用DirectByteBuffer。
1、HeapByteBuffer與DirectByteBuffer,在原理上,前者可以看出分配的buffer是在heap區域的,其實真正flush到遠程的時候會先拷貝得到直接內存,再做下一步操作(考慮細節還會到OS級別的內核區直接內存),其實發送靜態文件最快速的方法是通過OS級別的send_file,只會經過OS一個內核拷貝,而不會來回拷貝;在NIO的框架下,很多框架會採用DirectByteBuffer來操作,這樣分配的內存不再是在java
heap上,而是在C heap上,經過性能測試,可以得到非常快速的網路交互,在大量的網路交互下,一般速度會比HeapByteBuffer要快速好幾倍。
最基本的情況下
分配HeapByteBuffer的方法是:
ByteBuffer.allocate(int capacity);參數大小為位元組的數量
分配DirectByteBuffer的方法是:
ByteBuffer.allocateDirect(int capacity);//可以看到分配內存是通過unsafe.allocateMemory()來實現的,這個unsafe默認情況下java是沒有能力可以調用到的,不過你可以通過反射的手段得到實例進而做操作,當然你需要保證的是的穩定性,既然叫unsafe的,就是告訴你這不是安全的,其實並不是不安全,而是交給程序員來操作,它可能會因為程序員的能力而導致不安全,而並非它本身不安全。
由於HeapByteBuffer和DirectByteBuffer類都是default類型的,所以你無法位元組訪問到,你只能通過ByteBuffer間接訪問到它,因為JVM不想讓你訪問到它,對了,JVM不想讓你訪問到它肯定就有它不可告人的秘密;後面我們來跟蹤下他的秘密吧。
2、前面說到了,這塊區域不是在java heap上,那麼這塊內存的大小是多少呢?默認是一般是64M,可以通過參數:-XX:MaxDirectMemorySize來控制,你夠牛的話,還可以用代碼控制,呵呵,這裡就不多說了。
3、直接內存好,我們為啥不都用直接內存?請注意,這個直接內存的釋放並不是由你控制的,而是由full gc來控制的,直接內存會自己檢測情況而調用system.gc(),但是如果參數中使用了DisableExplicitGC 那麼這是個坑了,所以啊,這玩意,設置不設置都是一個坑坑,所以java的優化有沒有絕對的,只有針對實際情況的,針對實際情況需要對系統做一些拆分做不同的優化。
4、那麼full
gc不觸發,我想自己釋放這部分內存有方法嗎?可以的,在這裡沒有什麼是不可以的,呵呵!私有屬性我們都任意玩他,還有什麼不可以玩的;我們看看它的源碼中DirectByteBuffer發現有一個:Cleaner,貌似是用來搞資源回收的,經過查證,的確是,而且又看到這個對象是sun.misc開頭的了,此時既驚喜又鬱悶,呵呵,只要我能拿到它,我就能有希望消滅掉了;下面第五步我們來做個試驗。
<span style="color:#、因為我們的代碼全是私有的,所以我要訪問它不能直接訪問,我需要通過反射來實現,OK,我知道要調用cleaner()方法來獲取它Cleaner對象,進而通過該對象,執行clean方法;(付:以下代碼大部分也取自網路上的一篇copy無數次的代碼,但是那個代碼是有問題的,有問題的部分,我將用紅色標識出來,如果沒有哪條代碼是無法運行的)
import java.nio.ByteB
import sun.nio.ch.DirectB
public class DirectByteBufferCleaner {
public static void clean(final ByteBuffer byteBuffer) {
if (byteBuffer.isDirect()) {
((DirectBuffer)byteBuffer).cleaner().clean();
上述類你可以在任何位置建立都可以,這裡多謝一樓的回復,以前我的寫法是見到DirectByteBuffer類是Default類型的,因此這個類無法直接引用到,是通過反射去找到cleaner的實例,進而調用內部的clean方法,那樣做麻煩了,其實並不需要那麼麻煩,因為DirectByteBuffer
implements了DirectBuffer,而DirectBuffer本身是public的,所以通過介面去調用內部的Clear對象來做clean方法。
我們下面來做測試來證明這個程序是有效地回收的:
在任意一個地方寫一段main方法來調用,我這裡就直接寫在這個類裡面了:
public static void sleep(long i) {
Thread.sleep(i);
}catch(Exception e) {
public static void main(String []args) throws Exception {
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 100);
System.out.println("start");
sleep(10000);
clean(buffer);
System.out.println("end");
sleep(10000);
這裡分配了100M內存,為了將結果看清楚,在執行前,執行後分別看看延遲10s,當然你可以根據你的要求自己改改。請提前將OS的資源管理器打開,看看當前使用的內存是多少,如果你是linux當然是看看free或者用top等命令來看;本地程序我是用windows完成,在運行前機器的內存如下圖所示:
開始運行在輸入start後,但是未輸出end前,內存直接上升將近100m。
在輸入end後發現內存立即降低到2.47m,說明回收是有效的。
此時可以觀察JVM堆的內存,不會有太多的變化,注意:JVM本身啟動後也有一些內存開銷,所以不要將那個開銷和這個綁定在一起;這裡之所以一次性申請100m也是為了看清楚過程,其餘的可以做實驗玩玩了。
&&&&推薦文章:
【上篇】【下篇】DirectByteBuffer - lixjluck - ITeye技术网站
博客分类:
DirectByteBuffer特性说明
Java 2 SE 6 doc :
Given a direct byte buffer, the Java virtual machine will
make a best effort to perform native I/O operations directly upon it.
That is, it will attempt to avoid copying the buffer’s content to (or
from) an intermediate buffer before (or after) each invocation of one of
the underlying operating system’s native I/O operations.
DirectBuffer通过免去中间交换的内存拷贝, 提升IO处理速度;也就是常说的zero-copy
Java 2 SE 6 doc :
The contents of direct buffers may reside outside of the
normal garbage-collected heap, and so their impact upon the memory
footprint of an application might not be obvious.
DirectBuffer在-XX:MaxDirectMemorySize=xxM大小限制下[1], 使用Heap之外的内存, GC对此”无能为力”[2] ,也就意味着规避了在高负载下频繁的GC过程对应用线程的中断影响.
如果系统没有指定-XX:MaxDirectMemorySize,默认通-Xmx大小
//directMemory
String s = (String)
properties.remove("sun.nio.MaxDirectMemorySize");
if (s != null) if (s.equals("-1")) {
directMemory = Runtime.getRuntime().maxMemory();
long l = Long.parseLong(s);
if (l & -1L) directMemory =
DirectByteBuffer如何内存回收
实现了一个Cleaner
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
Deallocator,实现内存回收
if (address == 0) {
// Paranoia
unsafe.freeMemory(address);
address = 0;
Bits.unreserveMemory(size, capacity);
在什么时候被调用?
看看Reference里的奥秘,它内部有一个Thread ReferenceHandler,它的run 方法会调用Cleaner.clean
//截取部分代码
synchronized (lock) {
if (pending != null) {
Reference rn = r.
pending = (rn == r) ? null :
lock.wait();
} catch (InterruptedException x) { }
// Fast path for cleaners
if (r instanceof Cleaner) {
((Cleaner)r).clean();
DirectByteBuffer如何实现zero-copy
sun.nio.ch.IOUtil
static int read(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj)
throws IOException
ByteBuffer bytebuffer1;
if(bytebuffer.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if(bytebuffer instanceof DirectBuffer)
return readIntoNativeBuffer(filedescriptor, bytebuffer, l, nativedispatcher, obj);
bytebuffer1 =
bytebuffer1 = Util.getTemporaryDirectBuffer(bytebuffer.remaining());
int i = readIntoNativeBuffer(filedescriptor, bytebuffer1, l, nativedispatcher, obj);
bytebuffer1.flip();
bytebuffer.put(bytebuffer1);
Util.offerFirstTemporaryDirectBuffer(bytebuffer1);
Util.offerFirstTemporaryDirectBuffer(bytebuffer1);
NativeDispatcher的实现类SocketDispatcher的read方法是native
static native int read0(FileDescriptor filedescriptor, long l, int i) throws IOE
DirectByteBuffer用在什么地方
jetty用来处理和socket通信使用了DirectByteBuffer
-XX:MaxDirectMemorySize
This option specifies the maximum total size of java.nio (New I/O package) direct buffer allocations.
-XX:MaxDirectMemorySize=size[g|G|m|M|k|K]
java -XX:MaxDirectMemorySize=2g myApp
Default Value
The default value is zero, which means the maximum direct memory is unbounded.
参考:http://www.tbdata.org/archives/801
浏览: 62302 次
来自: 杭州
楼主,代码报错啊,麻烦发工程发邮箱下@qq. ...
/docs/ ...
天气api,haoservice的数据接口也不错,免费试用 h ...
这个接口怎么才能调用呢,我想采用js调用。
http://blog.csdn.net/axman/arti ...NIO DirectByteBuffer 内存泄露的测试 - 小程故事多 - ITeye技术网站
博客分类:
写NIO程序经常使用ByteBuffer来读取或者写入数据,那么使用ByteBuffer.allocate(capability)还是使用ByteBuffer.allocteDirect(capability)来分配缓存了?第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢;第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。
我们肯定想选择比较快的,但问题是直接内存不属于GC管辖范围,需要弄清楚这部分内存如何管理,否则造成内存泄露就麻烦了。本地内存在JAVA中有一个对应的包装类DirectByteBuffer,该类属于Java类,适当的时候会被GC回收,当它被回收前会调用本地方法把直接内存给释放了,所以本地内存可以随DirectByteBuffer对象被回收而自动回收,貌似没有问题;但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那程序就直接崩溃了。
有没有解决方案?自动释放不靠谱,我们是否可以手动释放本地内存,把握主动权?果然DirectByteBuffer持有一个Cleaner对象,该对象有一个clean()方法可用于释放本地内存,所以需要的时候我们可以调用这个方法手动释放本地内存。
以下代码与测试场景帮助理解与证实以上描述。
package com.stevex.app.
import java.nio.ByteB
import java.util.concurrent.TimeU
public class DirectByteBufferTest {
public static void main(String[] args) throws InterruptedException{
ByteBuffer bb = ByteBuffer.allocateDirect(1024*1024*128);
TimeUnit.SECONDS.sleep(10);
System.out.println("ok");
测试用例1:设置JVM参数-Xmx100m,运行异常,因为如果没设置-XX:MaxDirectMemorySize,则默认与-Xmx参数值相同,分配128M直接内存超出限制范围。
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.&init&(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
at com.stevex.app.nio.DirectByteBufferTest.main(DirectByteBufferTest.java:8)
测试用例2:设置JVM参数-Xmx256m,运行正常,因为128M小于256M,属于范围内分配。
测试用例3:设置JVM参数-Xmx256m -XX:MaxDirectMemorySize=100M,运行异常,分配的直接内存128M超过限定的100M。
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.&init&(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
at com.stevex.app.nio.DirectByteBufferTest.main(DirectByteBufferTest.java:8)
package com.stevex.app.
import java.nio.ByteB
import java.util.concurrent.TimeU
import sun.nio.ch.DirectB
public class DirectByteBufferTest {
public static void main(String[] args) throws InterruptedException{
ByteBuffer bb = ByteBuffer.allocateDirect(1024*1024*512);
TimeUnit.SECONDS.sleep(10);
((DirectBuffer)bb).cleaner().clean();
TimeUnit.SECONDS.sleep(10);
System.out.println("ok");
测试用例4:设置JVM参数-Xmx768m,运行程序观察内存使用变化,会发现clean()后内存马上下降,说明使用clean()方法能有效及时回收直接缓存。
浏览: 358925 次
来自: 北京
有jar包吗?
很好,学习了!分享一个基于支付系统场景的,尤其是在订单业务、资 ...
/darren/netty ...
看到楼主对FastDFS的封装,可以发我一份吗?邮箱:2113 ...

我要回帖

更多关于 蜜芽app下载 的文章

 

随机推荐