Java代码:
public class MainClass
{
static
{
System.load("/home/chronic/workspace/ramRead/src/libRamRead.so");
}
private native String readRam(int len, long addr, int pid);
private native int readSize();
public static void main(String[] args)
{
MainClass app = new MainClass();
String x = app.readRam(4096, 0x55c5520b5000L, 4435);
//System.out.println("HEY THERE");
// System.out.println("I BEGIN HERE");
System.out.println(x.length());
//int test = app.readSize();
//System.out.println(test);
}
}
这是我的本机函数(C++)
JNIEXPORT jstring JNICALL Java_ramRead_MainClass_readRam
(JNIEnv *env, jobject, jint len, jlong addr, jint pid)
{
struct iovec local[1];
struct iovec remote[1];
char buf[len];
jstring result;
//jcharArray buf = (*env).NewCharArray(len);
//jcharArray buf1 = (*env).NewCharArray(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);
//printf("len %d, pid %d, addr %li, buf %c, size of buf %d ", len, pid, addr, buf, sizeof(buf));
printf("\nTHIS MUCH: %d\n", nread);
for(int i=0; i<4096; i++){
printf("%c", buf[i]);
}
//(*env).SetCharArrayRegion(buf1, 0, len, buf);
result = (*env).NewStringUTF(buf);
//printf("RESULT: %s", (*env).GetStringUTFLength(result));
return result;
}
我的目标:
让 C++ 中的本机函数读取 ram 的内容,然后将其作为字符串或字符数组返回给 java 以进行进一步处理。
问题:
的返回值jstring result
不是我在 java 中所期望的,有几个问题,首先它的长度为 7 而不是预期的 4096。另一个问题是输出是无意义的。我有另一个用 C++ 编写的程序,它基本上读取 RAM 的内容,然后将它们打印到控制台。这是下面的代码,它就像一个魅力一样。我知道从哪个地址读取,我知道期望什么结果,只要我使用 C++,它就可以正常工作,但只要我使用 JNI 相同之前提到的问题发生的方法。
#include <jni.h>
#include "ramRead_MainClass.h"
#include <sys/uio.h>
static ssize_t nread;
JNIEXPORT jbyteArray JNICALL Java_ramRead_MainClass_readRam
(JNIEnv *env, jobject, jint len, jlong addr, jint pid)
//JNIEXPORT jbyteArray JNICALL Java_ramRead_MainClass_readRam
//(JNIEnv *env, jobject, jobject len, jobject addr, jint pid)
{
struct iovec local[1];
struct iovec remote[1];
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;
}
JNIEXPORT jint JNICALL Java_ramRead_MainClass_readSize
(JNIEnv *, jobject)
{
return nread;
}
到目前为止我尝试过的:
检查清单 1. 不是权限问题 2. Ram 地址是正确的,我知道那里存储了什么。我怎么知道?我正在读取计算器的 RAM,我正在寻找我输入的一组特定数字。使用 C++ 我找到了它们,但实际上不是 jni。3. 阅读有关 UTF_8 和 UTF_16 的更多信息(问题很可能出在这里) 4. 在这里看到的帖子试图重现解决方案,但无济于事。
操作系统:Linux 64 位 Fedora
问题:
如何将 C++ 字符串转换为 jstring,然后在 java 中返回它并打印出来,以便输出与上面列出的 C++ 程序的输出匹配。
无论如何,这就是我打算解决它的方式,但是如果有人有更好的解决方案或只是功能性解决方案,我会更乐意接受它们。
那么你们都为你的时间和努力。
JNI 以修改后的 utf-8 编码存储字符串(参见页面底部)。
如果您想继续使用字符串,那么您必须将您的字节转换为这种修改后的 utf-8 编码(因此字节值 >127 和零必须转换为 2 个字节)。
但正如 Jorn 在评论中所建议的,您将希望使用ByteBuffer
或 一个简单的字节数组 ( byte[]
) ,因为它更优化:使用String
,您会浪费内存,因为它包含 16 位元素。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句