Entrance Bytebuffer.allocatedirect
Public Static Bytebuffer allocatedirect (int capacity) { returnnew Directbytebuffer ( capacity); }
Directbytebuffer constructor function
Directbytebuffer (intCAP) {//package-private Super(-1, 0, Cap, CAP); BooleanPA =vm.isdirectmemorypagealigned (); intPS =bits.pagesize (); LongSize = Math.max (1L, (Long) Cap + (PA? ps:0)); Bits.reservememory (size, cap); LongBase = 0; Try{Base=unsafe.allocatememory (size); } Catch(OutOfMemoryError x) {bits.unreservememory (size, cap); Throwx; } unsafe.setmemory (base, size, (byte) 0); if(PA && (base% PS! = 0)) { //Round up to page boundaryAddress = base + PS-(Base & (ps-1)); } Else{Address=Base; } Cleaner= Cleaner.create ( This,NewDeallocator (base, size, cap)); Att=NULL; }
The JDK uses DirectByteBuffer
objects to represent out-of-heap memory, and each DirectByteBuffer
object, when initialized, creates a pair of objects that Cleaner
Cleaner
will execute at the appropriate time
unsafe.freeMemory(address)
To reclaim this out-of-heap memory. When initializing a block of out-of-heap memory, the object's reference relationship is as follows:
first
It is a Cleaner
static variable of the class, which is Cleaner
added to the list when initialized, Clener
and first
a reference relationship ReferenceQueue
is used to save the object that needs to be recycled Cleaner
.
If the DirectByteBuffer
object is recycled in a GC
At this point, only the Cleaner
object holds the data for the out-of-heap memory (start address, size, and capacity), puts the object into the next full GC, Cleaner
ReferenceQueue
and triggers the clean
method.
1. Creation of out-of-heap memory
In Directbytebuffer, first to the bits class to apply for a quota, the BITS class has a global totalcapacity variable, records the total size of all directbytebuffer, each application, first to see whether the overrun,
The quota for out-of-heap memory is by default similar to the in-heap memory (set by-XMX) and can be-xx:maxdirectmemorysize reset. If it is already overrun, it will proactively execute SYTEM.GC () and expect to proactively reclaim a bit of out-of-heap memory.
Then hibernate 100 milliseconds to see if the totalcapacity down no, if the memory is still insufficient, throw an Oom exception. If the quota is approved, call the famous Sun.misc.Unsafe to allocate memory.
2. Out-of-heap memory based on GC recycling
The Directbytebuffer object that exists in the heap is small, with only a few properties, such as the base address and size, and a cleaner, but it represents a large portion of memory allocated behind it, which is called an Iceberg object.
Quickly review the GC mechanism inside the heap, and when the new generation is full, young GC will occur, and if the object is not invalidated, it will not be recycled; After several times, the object is migrated to Laosheng generation;
Full GC will occur when the Laosheng is filled. Here you can see an awkward situation, because the directbytebuffer itself is very small, as long as the young GC survived, even if it has failed to
In the Laosheng generation comfortable stay, not easy to Laosheng generation burst trigger full GC, if no other large into the Laosheng generation trigger full GC, has been in that consumption, occupy a large heap outside memory does not release.
At this point, you can only rely on the previously mentioned limit of the amount of time to trigger the System.GC () to rescue. But this last insurance is not really good, first it interrupts the entire process, and then it makes the current thread
Slept for a full 100 milliseconds, and if the GC did not complete within 100 milliseconds, it would still mercilessly throw an oom exception. And, in case, if you're superstitious, a tuning guide sets-DISABLEEXPLICITGC.
Ban System.GC (), it is not fun. So, the outside of the heap memory is still self-active point recycling better, such as Netty is doing.
3. Active recovery of out-of-heap memory
For Sun's JDK this is actually very simple, just remove the sun.misc.Cleaner from the Directbytebuffer and then call its clean () line.
In Netty, because he is unsure of running in Sun's JDK (such as Android), it has wasted some effort to determine cleaner's existence.
4. How is cleaner associated with GC?
Cleaner is the Phantomreference subclass.
When the GC finds that it is unreachable except phantomreference (the Directbytebuffer that holds the cleaner fails), it is placed in the reference class pending list static variable.
Then there is another Referencehandler thread, followed by the pending list, and if you see the object type is cleaner, it will execute its clean (); If other types are placed in the Referencequeue,
Such applied code can drag out these theoretically dead objects from the queue, which is a much lighter and better mechanism than finalizer.
Reference:
is Java directbytebuffer wrappers garbage collected?
Small Wolf: Directbytebuffer
Jiangnan White: Out-of-heap memory
Java out-of-heap memory