I was referring to com.sun.jna.ptr.ByReference.
For background, the biggest use of native memory in my project is collecting Windows performance counters. For someone wanting to replicate a process listing similar the Windows Task Manager, each of 8 counters, for each process is queried. Assuming 100 processes queried every second, that's 800 queries. Each one involves the creation of a HANDLEByReference and populates counter information in a PDH_RAW_COUNTER structure. With the current “finalizer” code, these 1600 Memory allocations don’t get promptly released. The change to use cleaners improves on that.
However, I’d like to use the fact that Memory is now closeable to more promptly release the native memory resource, even before the Cleaner gets to it.
Here's the current code for the structure:
public static long queryCounter(WinNT.HANDLEByReference counter) {
PDH_RAW_COUNTER counterValue = new PDH_RAW_COUNTER();
int ret = PDH.PdhGetRawCounterValue(counter.getValue(), PDH_FMT_RAW, counterValue);
if (ret != WinError.ERROR_SUCCESS) {
if (LOG.isWarnEnabled()) {
LOG.warn("Failed to get counter. Error code: {}", String.format(FormatUtil.formatError(ret)));
}
return ret;
}
return counterValue.FirstValue;
}
This can be easily modified to use closeable memory:
public static long queryCounter(WinNT.HANDLEByReference counter) {
try (Memory m = new Memory(RAW_COUNTER_BYTES)) {
PDH_RAW_COUNTER counterValue = new PDH_RAW_COUNTER(m);
int ret = PDH.PdhGetRawCounterValue(counter.getValue(), PDH_FMT_RAW, counterValue);
if (ret != WinError.ERROR_SUCCESS) {
if (LOG.isWarnEnabled()) {
LOG.warn("Failed to get counter. Error code: {}", String.format(FormatUtil.formatError(ret)));
}
return ret;
}
return counterValue.FirstValue;
}
}
So I don't need to make any changes to the Structure code.
However, I can’t do the same with that HANDLEByReference argument. I allocate it here:
// Get a new handle for the counter
HANDLEByReference p = new HANDLEByReference();
if (!PerfDataUtil.addCounter(this.queryHandle, counter.getCounterPath(), p)) {
LOG.warn("Failed to add counter for PDH counter: {}", counter.getCounterPath());
return false;
}
counterHandleMap.put(counter, p);
And remove all references to it here, making it eligible for GC:
HANDLEByReference href = counterHandleMap.remove(counter);
// null if handle wasn't present
if (href != null) {
success = PerfDataUtil.removeCounter(href);
}
What I would LIKE to do is something like this when creating it:
Memory m = new Memory(Native.POINTER_SIZE);
HANDLEByReference p = new HANDLEByReference(m);
And when I’m done with it:
HANDLEByReference href = counterHandleMap.remove(counter);
// null if handle wasn't present
if (href != null) {
success = PerfDataUtil.removeCounter(href);
href.close();
}
This is not directly possible because HANDLEByReference extends com.sun.jna.ptr.ByReference and the only constructor takes a size argument, doing this:
protected ByReference(int dataSize) {
setPointer(new Memory(dataSize));
}
One possibility with the existing code is to retrieve the pointer, and cast it to Memory to call close(), e.g.,
HANDLEByReference href = counterHandleMap.remove(counter);
// null if handle wasn't present
if (href != null) {
success = PerfDataUtil.removeCounter(href);
Pointer p = href.getPointer();
if (p != null && p instanceof com.sun.jna.Memory) {
(Memory) p.close();
}
}
While this would work, casting always makes me uncomfortable. I would prefer to do one of the following:
I’m leaning toward 1 above, but can’t decide when to release the memory, and think 2 is a lot more flexible but also requires a lot more changes. Or I can just do the casting check which I’ll probably end up doing if I can’t decide on anything else. Or I might just use the try-with-resources with the Structure, and leave the HANDLEByReference as they are and trust the Cleaner to do its job.
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/2ea959cf5b727fa61a54c0d2c5c60ca8c3edc18b.camel%40doppel-helix.eu.