<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0">
I have discovered a bug in the Direct$Type$Buffer$RW$(int cap) constructor if the allocation of the cleaner fails as memory will be leaked if an Exception or Error is thrown by the allocation of the Deallocator or the creation of the cleaner.</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0">
<br>
</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1">
Here is how the allocation bug in the <span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted9">Direct$Type$Buffer$RW$(int cap) constructor</span> can be fixed:</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted8 ContentPasted10 ContentPasted11">
private static class Deallocator
<div class="ContentPasted11"> implements Runnable</div>
<div class="ContentPasted11"> {</div>
<div class="ContentPasted11"> private final long address;</div>
<div class="ContentPasted11"> private final long size;</div>
<div class="ContentPasted11"> private final int capacity;</div>
<div class="ContentPasted11"> private int deallocationPerformed;</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> private static final long DEALLOCATION_PERFORMED =</div>
<div class="ContentPasted11"> UNSAFE.objectFieldOffset(Deallocator.class, "deallocationPerformed");</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> private Deallocator(long address, long size, int capacity) {</div>
<div class="ContentPasted11"> assert (address != 0);</div>
<div class="ContentPasted11"> this.address = address;</div>
<div class="ContentPasted11"> this.size = size;</div>
<div class="ContentPasted11"> this.capacity = capacity;</div>
<div class="ContentPasted11"> }</div>
<div><br class="ContentPasted11">
</div>
<div class="ContentPasted11"> public void run() {</div>
<div class="ContentPasted11"> if(UNSAFE.getAndSetIntAcquire(this, DEALLOCATION_PERFORMED, 1) == 0) {</div>
<div class="ContentPasted11"> UNSAFE.freeMemory(address);</div>
<div class="ContentPasted11"> Bits.unreserveMemory(size, capacity);</div>
<div class="ContentPasted11"> }</div>
<div class="ContentPasted11"> }</div>
<div class="ContentPasted11"> }</div>
<div><br class="ContentPasted11">
</div>
<div class="ContentPasted11"> // Primary constructor</div>
<div class="ContentPasted11"> //</div>
<div class="ContentPasted11"> Direct$Type$Buffer$RW$(int cap) { // package-private</div>
<div class="ContentPasted11">#if[rw]</div>
<div class="ContentPasted11"> super(-1, 0, cap, cap);</div>
<div class="ContentPasted11"> boolean pa = VM.isDirectMemoryPageAligned();</div>
<div class="ContentPasted11"> int ps = Bits.pageSize();</div>
<div class="ContentPasted11"> long size = Math.max(1L, (long)cap + (pa ? ps : 0));</div>
<div class="ContentPasted11"> Bits.reserveMemory(size, cap);</div>
<div><br class="ContentPasted11">
</div>
<div class="ContentPasted11"> long base = 0;</div>
<div class="ContentPasted11"> Deallocator deallocator = null;</div>
<div class="ContentPasted11"> try {</div>
<div class="ContentPasted11"> base = UNSAFE.allocateMemory(size);</div>
<div class="ContentPasted11"> UNSAFE.setMemory(base, size, (byte) 0);</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> if (pa && (base % ps != 0)) {</div>
<div class="ContentPasted11"> // Round up to page boundary</div>
<div class="ContentPasted11"> address = base + ps - (base & (ps - 1));</div>
<div class="ContentPasted11"> } else {</div>
<div class="ContentPasted11"> address = base;</div>
<div class="ContentPasted11"> }</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> deallocator = new Deallocator(base, size, cap);</div>
<div class="ContentPasted11"> cleaner = Cleaner.create(this, deallocator);</div>
<div class="ContentPasted11"> } catch(Throwable ex) {</div>
<div class="ContentPasted11"> if(deallocator != null) {</div>
<div class="ContentPasted11"> deallocator.run();</div>
<div class="ContentPasted11"> } else {</div>
<div class="ContentPasted11"> if(base != 0)</div>
<div class="ContentPasted11"> UNSAFE.freeMemory(base);</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> Bits.unreserveMemory(size, capacity);</div>
<div class="ContentPasted11"> }</div>
<div class="ContentPasted11"> </div>
<div class="ContentPasted11"> throw ex;</div>
<div class="ContentPasted11"> }</div>
<div class="ContentPasted11"> att = null;</div>
<div class="ContentPasted11">#else[rw]</div>
<div class="ContentPasted11"> super(cap);</div>
<div class="ContentPasted11"> this.isReadOnly = true;</div>
<div class="ContentPasted11">#end[rw]</div>
}</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted8 ContentPasted10 ContentPasted11">
<br>
</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted8 ContentPasted10 ContentPasted11">
The updated version of the <span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted12">Direct$Type$Buffer$RW$(int cap) above will ensure that the memory that was allocated by <span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted13">UNSAFE.allocateMemory(size)
will get freed if the creation of the cleaner fails.</span></span></div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted8 ContentPasted10 ContentPasted11">
<span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted12"><span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted13"><br>
</span></span></div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted8 ContentPasted10 ContentPasted11">
<span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted12"><span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted13">A <span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted14">deallocationPerformed
field is also added to the Deallocator class to make sure that the memory that was allocated by the
<span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted15">
Direct$Type$Buffer$RW$(int cap) </span>is freed exactly once. A <span style="background-color:rgb(255, 255, 255);display:inline !important" class="ContentPasted16">UNSAFE.getAndSetIntAcquire is used to set deallocationPerformed to 1 in the Deallocator.run()
method to make sure that the deallocation of memory by Deallocator.run is performed only once.</span></span></span></span></div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted2 ContentPasted3 ContentPasted4">
</div>
</body>
</html>