亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java 之JNA中的Memory和Pointer的使用方法

 更新時間:2022年04月18日 16:45:31   作者:程序那些事  
這篇文章主要介紹了java 之JNA中的Memory和Pointer的使用方法,文章基于Java的相關自來哦展開對Pointer和Memory的使用介紹,需要的小伙伴可以參考一下

簡介

我們知道在native的代碼中有很多指針,這些指針在JNA中被映射成為Pointer。除了Pointer之外,JNA還提供了更加強大的Memory類,本文將會一起探討JNA中的PointerMemory的使用。

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方法,我們繼續(xù)看一下這個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方法,用來創(chuàng)建不可讀也不可寫的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引用的對象只要垃圾回收執(zhí)行,就會被回收,而不管是否內存不足。

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。 最后將新創(chuàng)建的對象加入到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就是來判斷訪問的地址是否出界,用來保證程序的安全。

總結

Pointer和Memory算是JNA中的高級功能,大家如果想要和native的alloc方法進行映射的話,就要考慮使用了。

到此這篇關于java 之JNA中的Memory和Pointer的使用方法的文章就介紹到這了,更多相關 Memory和Pointer內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • SSM框架前后端信息交互實現流程詳解

    SSM框架前后端信息交互實現流程詳解

    這篇文章主要介紹了SSM框架前后端信息交互實現流程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • java阻塞隊列BlockingQueue詳細解讀

    java阻塞隊列BlockingQueue詳細解讀

    這篇文章主要介紹了java阻塞隊列BlockingQueue詳細解讀,在新增的Concurrent包中,BlockingQueue很好的解決了多線程中,如何高效安全“傳輸”數據的問題,通過這些高效并且線程安全的隊列類,為我們快速搭建高質量的多線程程序帶來極大的便利,需要的朋友可以參考下
    2023-10-10
  • SpringCloud集成Nacos的使用小結

    SpringCloud集成Nacos的使用小結

    這篇文章主要介紹了SpringCloud集成Nacos的使用小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Spring Boot學習入門之統(tǒng)一異常處理詳解

    Spring Boot學習入門之統(tǒng)一異常處理詳解

    我們在做Web應用的時候,請求處理過程中發(fā)生錯誤是非常常見的情況。下面這篇文章主要給大家介紹了關于Spring Boot學習入門之統(tǒng)一異常處理的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2017-09-09
  • Default Methods實例解析

    Default Methods實例解析

    這篇文章主要介紹了Default Methods實例解析,介紹了默認方法的相關問題,以及與普通方法的區(qū)別,具有一定參考價值,需要的朋友可以了解下。
    2017-09-09
  • spring data 連接mongodb的兩種方式

    spring data 連接mongodb的兩種方式

    這篇文章主要介紹了spring data mongodb連接方式詳解,本文給大家分享兩種連接方式,通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2021-08-08
  • 部署Nacos的源碼環(huán)境搭建過程

    部署Nacos的源碼環(huán)境搭建過程

    這篇文章主要為大家介紹了部署Nacos的源碼環(huán)境搭建過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • java中的取整與四舍五入方法實例

    java中的取整與四舍五入方法實例

    這篇文章主要給大家介紹了關于java中取整與四舍五入的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • SpringBoot Entity中枚舉類型詳細使用介紹

    SpringBoot Entity中枚舉類型詳細使用介紹

    本文介紹SpringBoot如何在Entity(DAO)中使用枚舉類型。(本文使用MyBatis-Plus)。在實際開發(fā)中,經常會遇到表示類型或者狀態(tài)的情況,比如:有三種支付方式:微信、支付寶、銀聯。本文介紹如何這種場景的方案對比,并用實例來介紹如何用枚舉這種最優(yōu)雅的來表示
    2022-10-10
  • Spring使用IOC與DI實現完全注解開發(fā)

    Spring使用IOC與DI實現完全注解開發(fā)

    IOC也是Spring的核心之一了,之前學的時候是采用xml配置文件的方式去實現的,后來其中也多少穿插了幾個注解,但是沒有說完全采用注解實現。那么這篇文章就和大家分享一下,全部采用注解來實現IOC + DI
    2022-09-09

最新評論