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的内容,然后将其作为字符串或char数组返回给java进行进一步处理。
问题:
jstring result
的返回值不是我在java中的预期,有几个问题,首先它的长度为7而不是4096。 Antoher问题是输出是荒谬的。我有另一个用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的更多信息(问题很可能在这里) 这里看到的帖子试图重现解决方案,但无济于事。
操作系统:Linux 64位Fedora
问题:
如何将C ++字符串转换为jstring,然后在java中将其返回并打印出来,以便输出与上面列出的C ++程序的输出相匹配。
无论如何,这就是我打算解决它的方式,但如果有人有更好的解决方案或只是功能解决方案,我会更乐意接受它们。
然后你们都花时间和精力。
答案 0 :(得分:0)
JNI将字符串存储在modified utf-8 encoding中(参见本页底部)。
如果你想继续使用String,那么你必须将你的字节转换为这个修改过的utf-8编码(所以字节值> 127,零必须转换成2个字节)。
但正如Jorn在评论中所建议的那样,您将要使用ByteBuffer
或简单的字节数组(byte[]
),因为它更为理想:String
,你浪费内存,因为它包含16位元素。
答案 1 :(得分:-1)
我设法让它上班,但需要一些修修补补。这是下面的代码,可以与我发布的原始代码结合使用 很多人,我会尽力投票给答案。
在Java代码的主要内部,只需创建它以将字节数组转换为人类可读的字符。主题演讲,并非所有字符都会被正确转换,但就我的测试而言,所有特殊字符都是如此!“££%^&amp; *()_ + = - {} [] @〜:;'#&lt;&gt; ?,。/将打印出来没有问题加字母和数字AZ az 0-9如果你有一些英文字母之外的字母或类似的东西,你可能会遇到问题。
public static void main(String[] args){
MainClass app = new MainClass();
byte[] x = app.readRam(4096, 0x556cbdb2a000L, 22444);
System.out.println(x.length);
System.out.write(x, 0, x.length);
for(int i=0; i<x.length; i++)
{
if((int)x[i] >= 32 && (int)x[i] < 127)
{
System.out.print((char)x[i]);
}
}
char c = 120;
System.out.println("\n" + c);
}