源码版本5.15.0
Memory new出来了之后,不用手动去释放内存,Cleaner.getCleaner().register注册了之后会一直轮询直到对象被GC的时候,自动释放Native内存。
public Memory(long size) {
this.size = size;
if (size <= 0) {
throw new IllegalArgumentException("Allocation size must be greater than zero");
}
peer = malloc(size);
if (peer == 0)
throw new OutOfMemoryError("Cannot allocate " + size + " bytes");
allocatedMemory.put(peer, new WeakReference<>(this));
// GC时触发MemoryDisposer任务,释放内存
cleanable = Cleaner.getCleaner().register(this, new MemoryDisposer(peer));
}
private static final class MemoryDisposer implements Runnable {
private long peer;
public MemoryDisposer(long peer) {
this.peer = peer;
}
@Override
public synchronized void run() {
try {
free(peer);
} finally {
allocatedMemory.remove(peer);
peer = 0;
}
}
}
// Cleaner Starting CleanerThread 任务执行代码
@Override
public void run() {
while (true) {
try {
Reference<? extends Object> ref = referenceQueue.remove(CLEANER_LINGER_TIME);
if (ref instanceof CleanerRef) {
// CleanerRef为虚引用,当对象被GC的时候队列会有虚引用对象被塞进来,然后触发自定义的clean方法
((CleanerRef) ref).clean();
} else if (ref == null) {
synchronized (referenceQueue) {
Logger logger = Logger.getLogger(Cleaner.class.getName());
if (firstCleanable == null) {
cleanerThread = null;
logger.log(Level.FINE, "Shutting down CleanerThread");
break;
} else if (logger.isLoggable(Level.FINER)) {
StringBuilder registeredCleaners = new StringBuilder();
for(CleanerRef cleanerRef = firstCleanable; cleanerRef != null; cleanerRef = cleanerRef.next) {
if(registeredCleaners.length() != 0) {
registeredCleaners.append(", ");
}
registeredCleaners.append(cleanerRef.cleanupTask.toString());
}
logger.log(Level.FINER, "Registered Cleaners: {0}", registeredCleaners.toString());
}
}
}
} catch (InterruptedException ex) {
// Can be raised on shutdown. If anyone else messes with
// our reference queue, well, there is no way to separate
// the two cases.
// https://groups.google.com/g/jna-users/c/j0fw96PlOpM/m/vbwNIb2pBQAJ
break;
} catch (Exception ex) {
Logger.getLogger(Cleaner.class.getName()).log(Level.SEVERE, null, ex);
}
}
}