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/