java - 如何在 JNI 中访问 jobject 的值

标签 java c++ java-native-interface

JNIEXPORT jbyteArray JNICALL Java_ramRead_MainClass_readRam
        (JNIEnv *env, jobject, jobject len, jobject addr, jint pid)
{
        jclass c = (*env).GetObjectClass(len);
        jfieldID fid = (*env).GetFieldID(c, "len", "Ljava/math/BigInteger;");
        std::cout << "Object Field: " << (*env).GetObjectField(len, fid);

        struct iovec local[1];
        struct iovec remote[1];
        unsigned long long len1 = (*env).GetObjectField(len, fid) //This did not work out. the conversion to unsigned long long
        jbyte buf[len];
        jbyteArray buf1 = (*env).NewByteArray(len);

        local[0].iov_base = buf;
        local[0].iov_len = len;

        remote[0].iov_base = (void *) addr;
        remote[0].iov_len = len;

        nread = process_vm_readv(pid, local, 1, remote, 1, 0);

        (*env).SetByteArrayRegion(buf1, 0, len, buf);
        return buf1;
}

这是我的 native 方法,如您所见,它接收 3 个参数作为参数,两个 jobject 和一个 int。这两个工作对象是大整数, 最初它作为两个 int 和一个 long 参数恢复,但由于我现在需要传递大整数,所以我遇到了问题,或者我应该说几个。

目标:

我需要从 jobject len 中获取 BigInteger 值,然后我需要用它来初始化 jbyte buf[len] 的大小> , jbyteArray buf1 = (*env).NewByteArray(len)local[0].iov_len = len; 我当然不能只用 len 初始化它们 我需要从 len 中获取大整数值,然后用它初始化大小。 然后我需要做同样的事情,使用 jobject addr 从中提取大整数值。

如有任何帮助,我们将不胜感激。

最佳答案

你的方法的问题是你试图访问 BigInteger 调用 len 的字段:

GetFieldID(c, "len", "Ljava/math/BigInteger;");

但是 BigInteger 没有这样的字段。

无法直接访问 BigInteger 的“值”。您可以从 JNI 做的最好的事情是将 BigInteger 转换为 jlong​​(通过调用 Java 方法 longValue,在 BigInteger) 并使用它。

但是,如果要以任何方式将 BigInteger 转换为 jlong​​,则使用 BigInteger 毫无意义。您将失去使用 BigInteger 获得的任何精度。因此不妨在 Java 中使用 long(它仍然适合您提到的值 0xffffffffff601000)。

此外,一个byte[]只能被一个int索引,所以即使你让buf大于它,它也赢了' 可从 Java 访问。

我建议使用直接 ByteBuffer 而不是 byte[],因为您不必跨缓冲区复制数据。

你会得到这样的东西:

private static native void readRam(ByteBuffer buff, long address, int pid);

然后在 C++ 中:

JNIEXPORT void JNICALL Java_Main_readRam
    (JNIEnv *env, jclass, jobject byteBuffer, jlong addr jint pid) {

    struct iovec local[1];
    struct iovec remote[1];

    void* buf = env->GetDirectBufferAddress(byteBuffer);
    jlong len = env->GetDirectBufferCapacity(byteBuffer);

    local[0].iov_base = buf;
    local[0].iov_len = len;

    remote[0].iov_base = (void *) addr;
    remote[0].iov_len = len;

    process_vm_readv(pid, local, 1, remote, 1, 0);
}

然后调用:

int bufferLength = ...;
long address = 0xffffffffff601000L;
int pid = ...;

ByteBuffer bb = ByteBuffer.allocateDirect(bufferLength);

readRam(bb, address, pid);

// use bb...

关于您的评论,您可以这样做:

StringBuilder sb = new StringBuilder();
while(bb.hasRemaining()) {
    byte b = bb.get();
    if((b >= 32 && b < 127) || b == 10) {
        sb.append((char) b);
    }
}
String result = sb.toString();

关于java - 如何在 JNI 中访问 jobject 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44804660/

相关文章:

javascript - 通过RequestDispatcher调用html页面获取请求参数

java - 为什么我收到错误 'illegal start of type'

java - 无法在intellij idea中进行cucumber调试

c++ - 如何优化非线性方程组的解?

c++ - 比较 std::system_error::code() 和 std::errc::invalid_argument 时出现段错误

c++ - 运行使用 MinGW 构建的可执行文件时出现缺少 msvcr100.dll 错误

java - 使用 Cygwin 中启动的 perl 脚本运行带有 2 个参数的 Java 文件

c++ - 在 C++ 中使用冒泡排序对链表进行排序

android ndk jni No implementation found 错误

java - 如何将 Java double[][] 转换为 C++ <vector<vector>> JNI?