JNA中的Kernel32.INSTANCE.ReadProcessMemory确实很慢 [英] Kernel32.INSTANCE.ReadProcessMemory REALLY Slow In JNA

查看:205
本文介绍了JNA中的Kernel32.INSTANCE.ReadProcessMemory确实很慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个使用内存操作的游戏黑客,并决定在Java中针对FUD方面进行操作(几乎可以立即检测到本机黑客).

I'm writing a game hack which uses memory manipulation to work and decided to do it in Java for the FUD aspect (native hacks can be detected almost immediatly).

我有这种方法,可以从Windows调用ReadProcessMemory

I have this method which reads a memory object from the windows call ReadProcessMemory

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

Memory output = new Memory(bytesToRead); 有时大约需要0-5 + ms来执行

Memory output = new Memory(bytesToRead); Takes about 0-5+ms to execute sometimes

KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0); 大约需要0-5 + ms的时间来执行.

KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0); Takes about 0-5+ms as well to execute.

读取此信息的程序每个周期(16ms周期)调用这些方法大约1k次.

The program that reads this calls these methods about 1k times per cycle (16ms cycles).

我编写了一个基本的测试类来测试5000次呼叫将持续多长时间

I wrote a basic test class to test how long 5000 calls would be

public final class Test {
public static final int AMOUNT_OF_CALLS = 5000;

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

public static Memory readMemory(Pointer process, long address, int bytesToRead) {
    Memory output = new Memory(bytesToRead);
    Kernel32.INSTANCE.ReadProcessMemory(process, address, output, bytesToRead, 0);
    return output;
}

}

是否还有其他方法可以执行readMemory方法,以便执行所有5000次调用所需的时间少于32ms?

Is there any other way of doing the readMemory method so that it takes less than 32ms to execute all 5000calls?

推荐答案

您要在32毫秒内进行5000次呼叫.每次通话大约6us.您可以用纯C代码(不涉及Java)做到这一点吗?您可以在原始JNI中做到这一点吗?如果没有,那么尝试使其与JNA一起使用就没有多大意义了.不仅需要进行数据传输,而且还需要一些时间来处理这些数据.

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只是Java表示的malloc内存块,已在GC上释放.预先分配所需的不同块数,或创建直接的NIO缓冲区(这可以使对本机后备内存的调整更加有效).

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);
}

使用long代替Pointer(可能是YMMV),可能可能有所收获,并且始终测量增加的复杂性带来的影响.

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

这篇关于JNA中的Kernel32.INSTANCE.ReadProcessMemory确实很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆