Search code examples
javawinapijvmjna

Java JNA WinAPI function crash silently the JVM


I'm trying to call the winapi function CallNtPowerInformation from java with jna.

This is my code:

NativeProcessorPowerInformation[] systemProcessors = new NativeProcessorPowerInformation[getProcessorCount()];
for (int systemProcessorIndex = 0; systemProcessorIndex < systemProcessors.length; systemProcessorIndex++) {
    systemProcessors[systemProcessorIndex] = new NativeProcessorPowerInformation();
}

nativeLibraryPowrprof.CallNtPowerInformation(11, null, new NativeLong(0),
    systemProcessors[0], new NativeLong(systemProcessors.length * systemProcessors[0].size())
);

The dll is instantiated with this:

nativeLibraryPowrprof = Native.loadLibrary("powrprof", NativeLibraryPowrprof.class, W32APIOptions.DEFAULT_OPTIONS);

And this is the library interface I used:

public static interface NativeLibraryPowrprof extends StdCallLibrary {
    public int CallNtPowerInformation(int informationLevel, Pointer lpInputBuffer, NativeLong nInputBufferSize, Structure lpOutputBuffer, NativeLong nOutputBufferSize);

    @ToString
    public static class NativeProcessorPowerInformation extends Structure {
        public ULONG Number;
        public ULONG MaxMhz;
        public ULONG CurrentMhz;
        public ULONG MhzLimit;
        public ULONG MaxIdleState;
        public ULONG CurrentIdleState;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("Number", "MaxMhz", "CurrentMhz", "MhzLimit", "MaxIdleState", "CurrentIdleState");
        }
    }
}

This code works (for 10 seconds) the results are corrects, but sometimes after 10/20 seconds it crash the jvm silently, i get the exit code -1073740940 (Heap Corruption).

Maybe I'm missing something?


Solution

  • You are passing the address of the first Structure in a Java array that has been constructed from disparate Structure instances. The callee expects a contiguous block of memory, and you're only passing a block the size of a single structure but telling the callee it's the size of N structures.

    Use Structure.toArray() to get a block of contiguously allocated memory. You can then manipulate the members of the array if needed. JNA should automatically update all members of the array after the call.