Java Code:
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);
}
}
This is my native function (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;
}
My goal:
Have the native function in C++ read the contents of ram and then return it as a string or as a char array to java for further processing.
Problem:
The return value of the jstring result
is not what I expected it to be in java, there are several problems, first of all it has a length of 7 instead of 4096 as was intended. Antoher problem is the output is nonsensical. I have another program written in C++ which basically reads the contents of the RAM and then just prints them to a console. Here is the code bellow it works like a charm.I know from which address to read and I know what result to expect, and it does work without any problems so long as I am using C++ but as soon as I use JNI with the same methods before mentioned problems occur.
#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;
}
What I have tried thus far:
Check list 1. Not a permission problem 2. Ram address is correct and I know what is stored there. How do I know? I am reading RAM of a calculator, and I am looking for a specific set of numbers that I type in. With C++ I find them, but with jni not really. 3. Read more about UTF_8 and UTF_16 (there is a good chance the problem is here) 4. Seen posts here tried to reproduce the solutions, but to no avail.
OS: Linux 64 bit Fedora
Question:
How to convert a C++ string to a jstring and then return it in java and print it out so that the output would match the output of the C++ program listed above has.
Anyway this is how I intended to go about solving it, but if anyone has any better solutions or just functional solutions, I will more then gladly accept them.
Then you all for your time and effort.