java基礎-DirectByteBuffer

來源:互聯網
上載者:User

標籤:dir   error   pos   attach   cti   實現   runnable   nal   等級   

我們可以通過ByteBuffer建立一塊直接記憶體

ByteBuffer direct = ByteBuffer.allocateDirect(8);//建立8位元組空間的直接記憶體

 

1     public static ByteBuffer allocateDirect(int capacity) {2         return new DirectByteBuffer(capacity);3     }

 

 1     DirectByteBuffer(int cap) {                   // package-private 2         //mark, position, limit, capacity 3         super(-1, 0, cap, cap); 4         //後面的一大堆就是計算分配空間大小、分配、計算空間始址 5         boolean pa = VM.isDirectMemoryPageAligned(); 6         int ps = Bits.pageSize(); 7         long size = Math.max(1L, (long)cap + (pa ? ps : 0)); 8         Bits.reserveMemory(size, cap); 9 10         long base = 0;11         try {12             base = unsafe.allocateMemory(size);//使用unsafe來分配直接記憶體13         } catch (OutOfMemoryError x) {14             Bits.unreserveMemory(size, cap);15             throw x;16         }17         unsafe.setMemory(base, size, (byte) 0);18         if (pa && (base % ps != 0)) {19             // Round up to page boundary20             address = base + ps - (base & (ps - 1));21         } else {22             //address是始址,可知一個DirectByteBufferObject Storage Service了記憶體始址address、記憶體容量capacity,這已經可以確定一塊記憶體了,再加上position、limited、mark就可以對該記憶體進行緩衝式的讀寫操作了23             address = base;24         }25         cleaner = Cleaner.create(this, new Deallocator(base, size, cap));//用於回收直接記憶體26         att = null;//attachement27     }

對於記憶體空間,我們關注的是它的分配和回收,這裡使用了unsafe分配,unsafe是一個提供了低等級操作的介面,這裡就不研究它了,我們主要來看這塊被unsafe分配的直接記憶體是如何被回收的。

 

重點來看Cleaner.create(this, new Deallocator(base, size, cap))

Deallocator實現了Runnable,在run方法中使用unsafe.freeMemory(address)釋放了記憶體。

 1     private static class Deallocator 2         implements Runnable 3     { 4  5         private static Unsafe unsafe = Unsafe.getUnsafe(); 6  7         private long address; 8         private long size; 9         private int capacity;10 11         private Deallocator(long address, long size, int capacity) {12             assert (address != 0);13             this.address = address;14             this.size = size;15             this.capacity = capacity;16         }17 18         public void run() {19             if (address == 0) {20                 // Paranoia21                 return;22             }23             unsafe.freeMemory(address);24             address = 0;25             Bits.unreserveMemory(size, capacity);26         }27 28     }

 

1     public static Cleaner create(Object var0, Runnable var1) {2         //add是將cleaner執行個體存入由Cleaner維護的一個鏈表中,這裡的var0是DirectByteBuffer,var1是Deallocator3         return var1 == null ? null : add(new Cleaner(var0, var1));4     }5     private Cleaner(Object var1, Runnable var2) {6         //Cleaner繼承了PhantomReference,dummyQueue是一個假隊列,無用。這裡將DirectByteBuffer作為PhantomReference,Deallocator為thunk7         super(var1, dummyQueue);8         this.thunk = var2;9     }

 

之前有聊過Reference機制對於Cleaner的特殊處理,當HandlerThread從pending隊列中取到cleaner後,會執行其clean方法。下面就是clean方法,其中調用了thunk.run,該thunk對應Deallocator,run方法中就包含了unsafe.freeMemory,就此直接記憶體被釋放了。

 1     public void clean() { 2         if (remove(this)) {//從鏈表中刪除該cleaner 3             try { 4                 this.thunk.run();//執行Runnable邏輯 5             } catch (final Throwable var2) { 6                 AccessController.doPrivileged(new PrivilegedAction<Void>() { 7                     public Void run() { 8                         if (System.err != null) { 9                             (new Error("Cleaner terminated abnormally", var2)).printStackTrace();10                         }11 12                         System.exit(1);13                         return null;14                     }15                 });16             }17         }18     }

 

總結一下,申請直接記憶體其實就是構造了一個DirectByteBuffer執行個體,該執行個體會持有一個cleaner執行個體,當不再有強引用指向我們建立的DirectByteBuffer執行個體時,gc就會回收該執行個體,與此同時,PhantomReference類型的Cleaner也會被HandlerThread捕獲,並執行clean方法,該clean方法會調用thunk.run,對於DirectByteBuffer來說,thunk就是Deallocator,故直接記憶體得以釋放。

 

由上述可知,我們也可以自己控制直接記憶體的分配和釋放

1         long address = unsafe.allocateMemory(size);//分配2         unsafe.freeMemory(address);//釋放

 

java基礎-DirectByteBuffer

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.