|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.java2d.marlin; |
|
|
|
import java.lang.ref.PhantomReference; |
|
import java.lang.ref.ReferenceQueue; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Vector; |
|
import static sun.java2d.marlin.MarlinConst.logUnsafeMalloc; |
|
import sun.misc.ThreadGroupUtils; |
|
import sun.misc.Unsafe; |
|
|
|
|
|
|
|
|
|
*/ |
|
final class OffHeapArray { |
|
|
|
|
|
static final Unsafe unsafe; |
|
|
|
static final int SIZE_INT; |
|
|
|
|
|
private static final ReferenceQueue<Object> rdrQueue |
|
= new ReferenceQueue<Object>(); |
|
|
|
private static final Vector<OffHeapReference> refList |
|
= new Vector<OffHeapReference>(32); |
|
|
|
static { |
|
unsafe = Unsafe.getUnsafe(); |
|
SIZE_INT = Unsafe.ARRAY_INT_INDEX_SCALE; |
|
|
|
|
|
AccessController.doPrivileged( |
|
(PrivilegedAction<Void>) () -> { |
|
|
|
|
|
|
|
|
|
*/ |
|
final ThreadGroup rootTG |
|
= ThreadGroupUtils.getRootThreadGroup(); |
|
final Thread t = new Thread(rootTG, new OffHeapDisposer(), |
|
"MarlinRenderer Disposer"); |
|
t.setContextClassLoader(null); |
|
t.setDaemon(true); |
|
t.setPriority(Thread.MAX_PRIORITY); |
|
t.start(); |
|
return null; |
|
} |
|
); |
|
} |
|
|
|
|
|
long address; |
|
long length; |
|
int used; |
|
|
|
OffHeapArray(final Object parent, final long len) { |
|
|
|
this.address = unsafe.allocateMemory(len); |
|
this.length = len; |
|
this.used = 0; |
|
if (logUnsafeMalloc) { |
|
MarlinUtils.logInfo(System.currentTimeMillis() |
|
+ ": OffHeapArray.allocateMemory = " |
|
+ len + " to addr = " + this.address); |
|
} |
|
|
|
|
|
refList.add(new OffHeapReference(parent, this)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void resize(final long len) { |
|
|
|
this.address = unsafe.reallocateMemory(address, len); |
|
this.length = len; |
|
if (logUnsafeMalloc) { |
|
MarlinUtils.logInfo(System.currentTimeMillis() |
|
+ ": OffHeapArray.reallocateMemory = " |
|
+ len + " to addr = " + this.address); |
|
} |
|
} |
|
|
|
void free() { |
|
unsafe.freeMemory(this.address); |
|
if (logUnsafeMalloc) { |
|
MarlinUtils.logInfo(System.currentTimeMillis() |
|
+ ": OffHeapEdgeArray.free = " |
|
+ this.length |
|
+ " at addr = " + this.address); |
|
} |
|
} |
|
|
|
void fill(final byte val) { |
|
unsafe.setMemory(this.address, this.length, val); |
|
} |
|
|
|
static final class OffHeapReference extends PhantomReference<Object> { |
|
|
|
private final OffHeapArray array; |
|
|
|
OffHeapReference(final Object parent, final OffHeapArray edges) { |
|
super(parent, rdrQueue); |
|
this.array = edges; |
|
} |
|
|
|
void dispose() { |
|
|
|
this.array.free(); |
|
} |
|
} |
|
|
|
static final class OffHeapDisposer implements Runnable { |
|
@Override |
|
public void run() { |
|
final Thread currentThread = Thread.currentThread(); |
|
OffHeapReference ref; |
|
|
|
|
|
for (; !currentThread.isInterrupted();) { |
|
try { |
|
ref = (OffHeapReference)rdrQueue.remove(); |
|
ref.dispose(); |
|
|
|
refList.remove(ref); |
|
|
|
} catch (InterruptedException ie) { |
|
MarlinUtils.logException("OffHeapDisposer interrupted:", |
|
ie); |
|
} |
|
} |
|
} |
|
} |
|
} |