Java JNA 4.3.0 在查找进程时产生大量垃圾

Java JNA 4.3.0 Creates Insane Amout of Garbage When Looking for Process

当我试图通过名称查找虚假进程时,JNA 产生了大量垃圾。

这是分配的屏幕截图(大约 100k.sec)

这里是测试用例(使用JNA的4.3.0 SNAPSHOT)

import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Tlhelp32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;

/**
 * Created by Jonathan on 8/26/2016.
 */
public class Main {

    public static void main(String[] args) {
        while (true)
            openProcess("doesntexist.exe");
    }

    private static final WinDef.DWORD DWORD_ZERO = new WinDef.DWORD(0);
    private static final Tlhelp32.PROCESSENTRY32 entry = new Tlhelp32.PROCESSENTRY32.ByReference();

    private static WinNT.HANDLE openProcess(String processName) {
        WinNT.HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPALL, DWORD_ZERO);
        try {
            while (Kernel32.INSTANCE.Process32Next(snapshot, entry)) {
                String fileName = Native.toString(entry.szExeFile);
                if (processName.equals(fileName))
                    return Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_ALL_ACCESS, true, entry.th32ProcessID.intValue());
            }
        } finally {
            Kernel32.INSTANCE.CloseHandle(snapshot);
        }
        return null;
    }

}

最后是内存快照 https://dl.dropboxusercontent.com/u/91292881/ShareX/2016/08/JNA%204.3.0.snapshot

我强烈怀疑你的堆使用是在你的循环中重复创建新的 String 对象。

您的代码在另一个无限循环中执行进程搜索(遍历每个进程),因此您有效地一遍又一遍地执行这一行...

String fileName = Native.toString(entry.szExeFile);

在内部,Native.toString(char[] buf) 每次都创建一个 new String()

public static String toString(char[] buf) {
    int len = buf.length;
    for (int index = 0; index < len; index++) {
        if (buf[index] == '[=11=]') {
            len = index;
            break;
        }
    }

    if (len == 0) {
        return "";
    } else {
        return new String(buf, 0, len);
    }
}

这些String对象被用于测试相等性一次,然后被扔到堆上。

由于创建 String 的主要目的是测试相等性,您可以直接使用底层 char[] 数组来测试相等性。将 processName 转换为 char[] 并同时遍历两个数组,测试字符相等性直至 processName 的长度,并在 entry.szExeFile 的下一个字符中使用空终止符。