We can create a piece of direct memory via Bytebuffer
Bytebuffer Direct = Bytebuffer.allocatedirect (8); // Create direct memory for 8-byte space
1 Public Static Bytebuffer allocatedirect (int capacity) {2 returnnew Directbytebuffer (capacity); 3 }
1Directbytebuffer (intCAP) {//package-private2 //mark, position, limit, capacity3 Super(-1, 0, Cap, cap);4 //the next big pile is the calculation of allocation space size, allocation, computational space5 BooleanPA =vm.isdirectmemorypagealigned ();6 intPS =bits.pagesize ();7 LongSize = Math.max (1L, (Long) Cap + (PA? ps:0));8 bits.reservememory (size, cap);9 Ten LongBase = 0; One Try { ABase =unsafe.allocatememory (size); //Use unsafe to allocate direct memory -}Catch(OutOfMemoryError x) { - bits.unreservememory (size, cap); the Throwx; - } -Unsafe.setmemory (base, size, (byte) 0); - if(PA && (base% PS! = 0)) { + //Round up to page boundary -Address = base + PS-(Base & (ps-1)); +}Else { A //address is the initial address, it is known that a Directbytebuffer object stores the memory address, memory capacity capacity, which can be determined a piece of memory, plus position, limited, Mark can cache this memory for read-write operations. atAddress =Base; - } -Cleaner =Cleaner.create (This, new Deallocator (base, size, cap));//used to reclaim direct memory -ATT =NULL;//attachement -}
For memory space, we are concerned about its allocation and recycling, where the use of unsafe allocation, unsafe is a low-level operation of the interface, which is not studied here, we mainly see how the unsafe allocation of Direct memory is how to be recycled .
Focus on Cleaner.create (this, new Deallocator (base, size, cap))
Deallocator implements the runnable and frees up memory using unsafe.freememory (address) in the Run method.
1 Private Static classDeallocator2 ImplementsRunnable3 {4 5 Private Staticunsafe unsafe =Unsafe.getunsafe ();6 7 Private Longaddress;8 Private Longsize;9 Private intcapacity;Ten One PrivateDeallocator (LongAddressLongSizeintcapacity) { A assert(Address! = 0); - This. Address =address; - This. Size =size; the This. Capacity =capacity; - } - - Public voidrun () { + if(Address = = 0) { - //Paranoia + return; A } at unsafe.freememory (address); -Address = 0; - bits.unreservememory (size, capacity); - } - -}
1 Public StaticCleaner Create (Object var0, Runnable var1) {2 //Add is to save the cleaner instance in a linked list maintained by cleaner, where the var0 is Directbytebuffer,var1 is Deallocator3 returnVar1 = =NULL?NULL:Add(NewCleaner (var0, var1));4 }5 PrivateCleaner (Object var1, Runnable var2) {6 //Cleaner inherited the Phantomreference,dummyqueue is a false queue, useless. Here will Directbytebuffer as Phantomreference, deallocator for thunk7 Super(var1, dummyqueue);8 This. thunk =var2;9}
I've talked about the special handling of the reference mechanism for cleaner, and when Handlerthread takes cleaner from the pending queue, it executes its clean method. Here is the clean method, in which the thunk.run is called, and the thunk corresponds to the Deallocator,run method that contains the unsafe.freememory, and this direct memory is freed.
1 Public voidClean () {2 if(Remove ( This)) {//Remove the Cleaner from the list3 Try {4 This.Thunk.run();//Execute runnable Logic5}Catch(Finalthrowable var2) {6Accesscontroller.doprivileged (NewPrivilegedaction<void>() {7 PublicVoid Run () {8 if(System.err! =NULL) {9(NewError ("Cleaner terminated abnormally", VAR2)). Printstacktrace ();Ten } One ASystem.exit (1); - return NULL; - } the }); - } - } -}
To summarize, the application of direct memory is essentially a directbytebuffer instance that holds a cleaner instance, which is recycled when a strong reference is no longer directed to the Directbytebuffer instance we created, while the GC reclaims the instance. Phantomreference types of cleaner are also captured by Handlerthread, and the clean method is executed, The clean method calls Thunk.run, and for Directbytebuffer, thunk is deallocator, so direct memory is freed.
We can also control the allocation and release of direct memory by ourselves.
1 long address = unsafe.allocatememory (size); // Distribution 2 Unsafe.freememory (address); // Release
Java Foundation-directbytebuffer