有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

当我试图按名称查找假进程时,JNA正在制造大量垃圾

这是分配的屏幕截图(大约10万秒)

enter image description here

以下是测试用例(使用JNA的4.3.0快照)

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


共 (1) 个答案

  1. # 1 楼答案

    我强烈怀疑堆的使用是在循环中重复创建新的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] == '\0') {
                len = index;
                break;
            }
        }
    
        if (len == 0) {
            return "";
        } else {
            return new String(buf, 0, len);
        }
    }
    

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

    由于创建String的主要目的是测试相等性,因此可以直接使用底层char[]数组测试相等性。将processName转换为char[]并在两个数组上同时迭代,在^{的下一个字符中使用空终止符测试长度为processName的字符相等性