2017-04-03 72 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) –