91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JNA中的Memory和Pointer怎么使用

發布時間:2022-04-19 10:39:01 來源:億速云 閱讀:386 作者:iii 欄目:開發技術

這篇文章主要講解了“JNA中的Memory和Pointer怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JNA中的Memory和Pointer怎么使用”吧!

簡介

我們知道在native的代碼中有很多指針,這些指針在JNA中被映射成為Pointer。

Pointer

Pointer是JNA中引入的類,用來表示native方法中的指針。大家回想一下native方法中的指針到底是什么呢?

native方法中的指針實際上就是一個地址,這個地址就是真正對象的內存地址。所以在Pointer中定義了一個peer屬性,用來存儲真正對象的內存地址:

protected long peer;

實時上,Pointer的構造函數就需要傳入這個peer參數:

public Pointer(long peer) {
        this.peer = peer;
    }

接下來我們看一下如何從Pointer中取出一個真正的對象,這里以byte數組為例:

    public void read(long offset, byte[] buf, int index, int length) {
        Native.read(this, this.peer, offset, buf, index, length);
    }

實際上這個方法調用了Native.read方法,我們繼續看一下這個read方法:

static native void read(Pointer pointer, long baseaddr, long offset, byte[] buf, int index, int length);

可以看到它是一個真正的native方法,用來讀取一個指針對象。

除了Byte數組之外,Pointer還提供了很多其他類型的讀取方法。

又讀取就有寫入,我們再看下Pointer是怎么寫入數據的:

    public void write(long offset, byte[] buf, int index, int length) {
        Native.write(this, this.peer, offset, buf, index, length);
    }

同樣的,還是調用 Native.write方法來寫入數據。

這里Native.write方法也是一個native方法:

static native void write(Pointer pointer, long baseaddr, long offset, byte[] buf, int index, int length);

Pointer還提供了很多其他類型數據的寫入方法。

當然還有更加直接的get*方法:

public byte getByte(long offset) {
        return Native.getByte(this, this.peer, offset);
    }

特殊的Pointer:Opaque

在Pointer中,還有兩個createConstant方法,用來創建不可讀也不可寫的Pointer:

    public static final Pointer createConstant(long peer) {
        return new Opaque(peer);
    }

    public static final Pointer createConstant(int peer) {
        return new Opaque((long)peer & 0xFFFFFFFF);
    }

實際上返回的而是Opaque類,這個類繼承自Pointer,但是它里面的所有read或者write方法,都會拋出UnsupportedOperationException

    private static class Opaque extends Pointer {
        private Opaque(long peer) { super(peer); }
        @Override
        public Pointer share(long offset, long size) {
            throw new UnsupportedOperationException(MSG);
        }

Memory

Pointer是基本的指針映射,如果對于通過使用native的malloc方法分配的內存空間而言,除了Pointer指針的開始位置之外,我們還需要知道分配的空間大小。所以一個簡單的Pointer是不夠用了。

這種情況下,我們就需要使用Memory。

Memory是一種特殊的Pointer, 它保存了分配出來的空間大小。

我們來看一下Memory的定義和它里面包含的屬性:

public class Memory extends Pointer {
...
    private static ReferenceQueue<Memory> QUEUE = new ReferenceQueue<Memory>();
    private static LinkedReference HEAD; // the head of the doubly linked list used for instance tracking
    private static final WeakMemoryHolder buffers = new WeakMemoryHolder();
    private final LinkedReference reference; // used to track the instance
    protected long size; // Size of the malloc'ed space
...
}

Memory里面定義了5個數據,我們接下來一一進行介紹。

首先是最為重要的size,size表示的是Memory中內存空間的大小,我們來看下Memory的構造函數

    public Memory(long size) {
        this.size = size;
        if (size <= 0) {
            throw new IllegalArgumentException("Allocation size must be greater than zero");
        }
        peer = malloc(size);
        if (peer == 0)
            throw new OutOfMemoryError("Cannot allocate " + size + " bytes");

        reference = LinkedReference.track(this);
    }

可以看到Memory類型的數據需要傳入一個size參數,表示Memory占用的空間大小。當然,這個size必須要大于0.

然后調用native方法的malloc方法來分配一個內存空間,返回的peer保存的是內存空間的開始地址。如果peer==0,表示分配失敗。

如果分配成功,則將當前Memory保存到LinkedReference中,用來跟蹤當前的位置。

我們可以看到Memory中有兩個LinkedReference,一個是HEAD,一個是reference。

LinkedReference本身是一個WeakReference,weekReference引用的對象只要垃圾回收執行,就會被回收,而不管是否內存不足。

private static class LinkedReference extends WeakReference<Memory>

我們看一下LinkedReference的構造函數:

private LinkedReference(Memory referent) {
            super(referent, QUEUE);
        }

這個QUEUE是ReferenceQueue,表示的是GC待回收的對象列表。

我們看到Memory的構造函數除了設置size之外,還調用了:

reference = LinkedReference.track(this);

仔細看LinkedReference.track方法:

   static LinkedReference track(Memory instance) {
            // use a different lock here to allow the finialzier to unlink elements too
            synchronized (QUEUE) {
                LinkedReference stale;

                // handle stale references here to avoid GC overheating when memory is limited
                while ((stale = (LinkedReference) QUEUE.poll()) != null) {
                    stale.unlink();
                }
            }

            // keep object allocation outside the syncronized block
            LinkedReference entry = new LinkedReference(instance);

            synchronized (LinkedReference.class) {
                if (HEAD != null) {
                    entry.next = HEAD;
                    HEAD = HEAD.prev = entry;
                } else {
                    HEAD = entry;
                }
            }

            return entry;
        }

這個方法的意思是首先從QUEUE中拿出那些準備被垃圾回收的Memory對象,然后將其從LinkedReference中unlink。 最后將新創建的對象加入到LinkedReference中。

因為Memory中的QUEUE和HEAD都是類變量,所以這個LinkedReference保存的是JVM中所有的Memory對象。

最后Memory中也提供了對應的read和write方法,但是Memory中的方法和Pointer不同,Memory中的方法多了一個boundsCheck,如下所示:

    public void read(long bOff, byte[] buf, int index, int length) {
        boundsCheck(bOff, length * 1L);
        super.read(bOff, buf, index, length);
    }

    public void write(long bOff, byte[] buf, int index, int length) {
        boundsCheck(bOff, length * 1L);
        super.write(bOff, buf, index, length);
    }

為什么會有boundsCheck呢?這是因為Memory和Pointer不同,Memory中有一個size的屬性,用來存儲分配的內存大小。使用boundsCheck就是來判斷訪問的地址是否出界,用來保證程序的安全。

感謝各位的閱讀,以上就是“JNA中的Memory和Pointer怎么使用”的內容了,經過本文的學習后,相信大家對JNA中的Memory和Pointer怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

株洲县| 花莲市| 宣威市| 饶阳县| 黄石市| 洪江市| 南城县| 同仁县| 民权县| 苏尼特左旗| 松江区| 剑河县| 周口市| 千阳县| 黄浦区| 台东县| 平乡县| 蓬莱市| 黎川县| 丰宁| 阿克苏市| 金平| 特克斯县| 探索| 榆中县| 镇平县| 象州县| 延安市| 始兴县| 潮安县| 靖江市| 和硕县| 绥宁县| 克东县| 马龙县| 光泽县| 拉孜县| 栖霞市| 贺兰县| 农安县| 保靖县|