如何在 JNI 中访问 jobject 的值
How to access values of a jobject in JNI
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;
}
这是我的本机方法,如您所见,它接收 3 个参数作为参数两个jobject
和一个int
。两个 jobject 是大整数, 最初它作为参数恢复了两个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
(通过在BigInteger
上调用 Java 方法longValue
)并使用它。
但是,如果您以任何方式将其转换为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();
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 从C++dll访问C#中的一行主要参数
- 概念TS检查忽略私有访问修饰符
- 访问被拒绝后,c++中的故障保护代码
- 在c++中访问int到类对象的映射时出错
- 我想访问std::unique_ptr中的一个特定元素
- 为什么示例代码访问IUnknown中已删除的内存
- C++:无法访问声明的受保护成员
- 通过指向指针数组的指针访问子类的属性
- 如何在 JNI 中访问 jobject 的值