JNI

2017-06-28 12 views
0
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; 
} 

これは私のネイティブメソッドであり、あなたが見ることができるように、それは引数2 jobjectと1 intとして3つのパラメータを受け取りにjオブジェクトの値にアクセスする方法。 2つのjobjectsは大きな整数です 元はパラメータとして復活しましたintと1つはlongですが、今は大きな整数を渡す必要があるため、問題があります。JNI

目標:私はjobject lenからBigInteger値を取得する必要があり、その後、私は私が取得する必要があり、私はもちろん、単にlenでそれらを初期化できないjbyte buf[len]jbyteArray buf1 = (*env).NewByteArray(len)local[0].iov_len = len;のサイズを初期化するためにそれを使用する必要があります

大きな整数値をlenから取得し、それを使ってサイズを初期化します。 それから、大きな整数値を抽出するjobject addrを使って同じことをする必要があります。

ご協力いただければ幸いです。

+0

'BigInteger'をここで' unsigned long long'に変換しているのであれば、ここでそれを使用する点はありません。なぜJavaのlong型を渡すだけではないのですか? –

+0

さて、私は長い間変換しようとしましたが、動作しませんでした。なぜBigIntegerですか?これは16進数の例です。ffffffffff601000 – ChronicUser

答えて

0

あなたのアプローチの問題点は、BigIntegerコールlenのフィールドにアクセスしようとしているということです。

GetFieldID(c, "len", "Ljava/math/BigInteger;"); 

をしかし、そのようなフィールドをBigIntegerありません。

BigIntegerの「値」に直接アクセスする方法はありません。 JNIからできることは、BigIntegerjlong(のJavaメソッドlongValueを呼び出して)に変換して使用します。

jlongに変換する場合は、BigIntegerを使用しても意味がありません。 BigIntegerを使用すると得られる精度が失われます。したがって、代わりにlongをJavaで使用することもできます(前述の値0xffffffffff601000に適合する)。

は、intでしか索引付けできないため、bufを大きくしても、Javaからアクセスできません。

byte[]ではなく、直接ByteBufferを使用することをお勧めします。これは、バッファ間でデータをコピーする必要がないためです。

あなたはこのような何かを得るだろう:C++での

private static native void readRam(ByteBuffer buff, long address, int pid); 

そして:そして

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(); 
+0

ありがとうございます。以前はバイト配列と同様のものを試してみましたが、うまくいきましたが、私は必要と思った大きな整数とし、それは乱雑になりました。問題は、私がbb.hasRemaining()とbb.get()でByteBufferを読み込もうとしたときに、BufferUnderflowExceptionを取得しました。ドキュメントを読み込んでいますが、それを回避するためにシームできません。さらに、このバイトバッファの要素をcharとして解釈し、文字列に格納する必要があります。これは、私がバイト[]配列で行ったことです。 – ChronicUser

+0

バイト[] x = this.readRam(readSize、addr、PID); \t \t文字列s = ""; (; iは0をint型用 \t \t; = 32 &&(INT)X [i]は<127 )||(INT)X [I] == 10) \t \t \t { \t \t \t \t S = Sで+(CHAR)X [i]は、 \t \t \t} \t \t} \t \tリターンS。 – ChronicUser

+0

@ChronicUser私は答えを改訂しました。それは動作しますか? –