Kernel32.INSTANCE.ReadProcessMemory REALLY Slow In JNA

倖福魔咒の 提交于 2019-12-06 07:59:48

You want to do 5000 calls in 32ms. That's roughly 6us per call. Can you do that in pure C code (no Java involved)? Can you do that in raw JNI? If not, there's not much point in trying to get it to work with JNA. Not only do you have to do the data transfer, but you need some time to do processing of that data.

Memory is just a Java representation of a malloc'ed chunk of memory that gets freed on GC. Pre-allocate the number of different blocks that you need, or create a direct NIO buffer (which may allow tweaks to the native backing memory more efficiently).

After pre-allocation, make sure you're using direct mapping, then profile again to see where you're spending time.

public class MyKernel32 {
    static { Native.register(NativeLibrary.getInstance("kernel32", W32APIOptions.DEFAULT_OPTIONS)); }
    public static native long ReadProcessMemory(HANDLE process, long address, Pointer buffer, int size, IntByReference numRead);
}

You might get some gains by using long in place of Pointer, but YMMV, and always measure the effects of added complexity.

Firstly, I would always write memory handling in C/C++. But if you need to do it in Java, I would consider Creating one memory instance and pass it as a parameter, this will avoid the heap construction/disposal routines.

Something like:

public static void main(String[] args) throws InterruptedException {
    long start = System.currentTimeMillis();
    final Memory output = new Memory(8);
    for (int i = 0; i < AMOUNT_OF_CALLS; i++) {
        Memory m = readMemory(new Pointer(1), 0xFFFFFFF, ThreadLocalRandom.current().nextInt(1, 8), memory); //Random between a byte read, or long
    }
    System.out.println("Took " + (System.currentTimeMillis() - start) + "ms todo " + AMOUNT_OF_CALLS + " readMemory calls.");
}

public static Memory readMemory(Pointer process, long address, int bytesToRead, final Memory output) {
    output.setSize( bytesToRead ) ;
    KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0);
    return output;
}

Something like that - not sure if you have access to modify the Memory size or not, but ideally it could create storage that will accommodate all your results and you set the amount actually stored for each call. This should avoid costly heap work.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!