Search code examples
javamemory-managementmemory-leaksjava-native-interfacejna

JNA Memory Leak - How to fix?


        public static User32 USER32_INSTANCE = (User32) Native.loadLibrary("user32", User32.class);

        user32 = USER32_INSTANCE;

        user32.EnumWindows((hWnd, arg) -> {
          int size = 1024 * 8;
          char[] buffer = new char[size];
          USER32_INSTANCE.GetWindowTextW(hWnd, buffer, size);

          char[] buffer2 = new char[size];
          PointerByReference pointer = new PointerByReference();
          User32DLL.GetWindowThreadProcessId(hWnd, pointer);
          Pointer process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pointer.getValue());
          Psapi.GetModuleBaseNameW(process, null, buffer2, size);

          String result = Native.toString(buffer).trim();
          String proc = Native.toString(buffer2).trim();

          // ... (non-JNA stuff)
        }

I haven't touched C/C++ since college and I honestly have no clue how to actually free the memory here :(

I know that there's a memory leak - I did some profiling with YourKit and traced a memory leak to this block of code (specifically, it seems to be leaking in the GetWindowTextW call and the Native.toString() calls). Could someone just give me an example of how to properly free up whatever memory blocks are being used?

I see that Pointer has a clear() method, should I use that? But I don't know how to get the size (clear takes a length argument). I also see that there's a Memory type that subclasses Pointer, but according to instanceof, none of the Pointers I have right now are actually instances of that.


Solution

  • After opening a handle to a process with OpenProcess, you need to close the process handle with CloseHandle. Remember that OpenProcess returns a Handle, not a Pointer.

    Kernel32.INSTANCE.CloseHandle(process);
    

    Note also that JNA provides a pretty in-depth mapping of the Windows API out of the box in the net.java.dev.jna-platform package (I think?)