2017-04-03 107 views
0

我目前正試圖使用​​JNI獲取內存中字段的偏移量,以便能夠將字段值複製到堆內存中。我能夠使用字段的jFieldID獲取實例字段的偏移量。 jFieldID的最重要的30位表示實例字段的字段偏移量。問題在於靜態字段。 30位表示一個JNIid *。一個JNIid是一個包含一個int偏移量字段的結構,它可能是該字段的偏移量。現在我的問題是我如何獲得這個價值。我用下面的代碼段(假定ID是一個字段的jFieldID和address_shift是2)靜態字段的JNI字段ID

uintptr_t result = (uintptr_t) id >> address_shift; 
// offset field in JNIid struc is in offset 16 
jlong staticFieldoffsetAddress = result + 16; 
jint* staticFieldValuePointer = (jint*) staticFieldoffsetAddress; 

然而,這不給我任何值。我得到0這是不正確的,因爲我將它與我從java中的Unsafe.staticFieldOffset(Field)獲得的內容進行比較。我知道我可以從JNI調用這個方法並使用結果。但我希望它可以用於關鍵性能的應用程序。

+5

JNI用於讀取字段值提供的功能。我強烈建議您使用這些代替嘗試對特定的JNI實現進行反向工程。 –

+0

是的,我知道但我不想逐個複製字段值。所以我想獲得最小偏移量和最大值並且做一個副本內存。 –

+0

@MohamedOmer你爲什麼會認爲內存中的偏移不會改變? –

回答

1

也許你可以使用GetStaticFieldID方法?

public class Static { 
    private static int field; 

    private native void access(); 
    public static void main(String args[]) { 
     Static s = new Static(); 
     Static.field = 1; 
     s.access(); 
    } 
    static { 
     System.loadLibrary("Static"); 
    } 
} 

C源

#include "jni.h" 

JNIEXPORT void JNICALL 
Java_Static_access(JNIEnv *env, jobject obj) 
{ 
    jfieldID fieldId; 
    jint fieldValue; 

    jclass class = (*env)->GetObjectClass(env, obj); 

    fieldId = (*env)->GetStaticFieldID(env, class, "field", "I"); 
    if (fieldId == NULL) { 
     return; 
    } 
    fieldValue = (*env)->GetStaticIntField(env, class, fieldId); 
    printf("Value: %d\n", fieldValue); 
} 

編譯並執行

> javac Static.java 
> javah -jni Static 
> cc -g -shared -fpic -I${JAVA_HOME}/include \ 
-I${JAVA_HOME}/include/darwin \ 
static.c -o libStatic.dylib 
> java Static 
Value: 1 
+0

順便說一句 - 你可以在這裏找到更多的JNI示例:http://jnicookbook.owsiak.org/ – mko

+0

是的,我可以使用JNI獲取值。但我想從內存中複製這些值。想象一下,我在一個類中有10個靜態字段。我不想在循環中複製它們。我想得到最小偏移量和最大偏移量,然後做一個不安全的.copymemory將min值複製到(max + size) –