2010年10月22日 星期五

讓Putty能夠顯示中文字 in Ubuntu

在Ubuntu下,要讓Putty顯示中文字主要設定方式可分為兩個步驟

  • 設定Putty Translation編碼,如下圖所示
    1. 選擇 Translation >> Remote character set: UTF-8

  • 設定Putty window Fonts,如下圖所示
    1. 選擇 Fonts >> 按下 Font used for ordinary text (Change...)
    2. 選擇字型 "TlwgMono"

大功告成!


--- 特別感謝 David 技術教學 ---

2010年10月19日 星期二

Colorful man pages setting

  • Linux colorful man pages setting (for bash)
    • 開啟個人bash設定檔
    vi ~/.bashrc
  • 加入以下資料
  • # For colourful man pages
    export PAGER="`which less` -s"
    export BROWSER="$PAGER"
    export LESS_TERMCAP_mb=$'\E[01;34m'
    export LESS_TERMCAP_md=$'\E[01;34m'
    export LESS_TERMCAP_me=$'\E[0m'
    export LESS_TERMCAP_se=$'\E[0m'
    export LESS_TERMCAP_so=$'\E[01;44;33m'
    export LESS_TERMCAP_ue=$'\E[0m'
    export LESS_TERMCAP_us=$'\E[01;33m'
    
  • 讀取bash設定檔
  • source ~/.bashrc
  • 完成!

2010年10月14日 星期四

JNI - Local and Global References

  • Local References
  • A local reference is valid only within the dynamic context of the native method that creates it, and only within that one invocation of the native method.
    P.S. You must not write native methods that store a local reference in a static variable and expect to use the same reference in subsequent invocations.
    (Example) MyNewString(): It is a modified version of the MyNewString function in before, uses local references incorrectly.
    /* This code is illegal */
    jstring
    MyNewString(JNIEnv *env, jchar *chars, jint len)
    {
        static jclass stringClass = NULL;
        jmethodID cid;
        jcharArray elemArr;
        jstring result;
    
        if (stringClass == NULL) {
            stringClass = (*env)->FindClass(env, "java/lang/String");
            if (stringClass == NULL) {
                return NULL; /* exception thrown */
            }
        }
        /* It is wrong to use the cached stringClass here, because it may be invalid. */
        cid = (*env)->GetMethodID(env, stringClass, "<init>", "([C)V");
        ...
        elemArr = (*env)->NewCharArray(env, len);
        ...
        result = (*env)->NewObject(env, stringClass, cid, elemArr);
        (*env)->DeleteLocalRef(env, elemArr);
        return result;
    }
    
    The goal for caching stringClass in a static variable might have been to eliminate the overhead of repeatedly making the following function call:
    FindClass(env, "java/lang/String");
    
    This is not the right approach because FindClass returns a local reference to the java.lang.String class object. To see why this is a problem, suppose that the native method implementation of C.f calls MyNewString:
    JNIEXPORT jstring JNICALL
    Java_C_f(JNIEnv *env, jobject this)
    {
        char *c_str = ...;
        ...
        return MyNewString(c_str);
    }
    
  • Global References

2010年10月11日 星期一

Caching Field and Method IDs

Obtaining field and method IDs requires symbolic lookups based on the name and descriptor of the field or method. Symbolic lookups are relatively expensive.
How to reduce this overhead?
The idea is to compute field and method IDs and cache them for repeated uses later.
  • Caching at the Point of Use
  • Field and method IDs may be cached at the point where native code accesses the field values or performs method callbacks.
    (Example)InstanceFieldAccess.c: caches the field ID in static variables so that it need not be recomputed upon each invocation of the InstanceFieldAccess.accessField method.
    #include <stdio.h>
    #include <jni.h>
    
    JNIEXPORT void JNICALL 
    Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
    {
        static jfieldID fid_s = NULL; /* cached field ID for s */
        jstring jstr;
        const char *str;
    
        /* Get a reference to obj's class */
        jclass cls = (*env)->GetObjectClass(env, obj);
    
        printf("In C:\n");
    
        /* Look for the instance field s in cls */
        if (fid_s == NULL) {
            fid_s = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
            if (fid_s == NULL) {
                return; /* exception already thrown */
            }
        }
    
        /* Read the instance field s */
        jstr = (*env)->GetObjectField(env, obj, fid_s);
        str = (*env)->GetStringUTFChars(env, jstr, NULL);
        if (str == NULL) {
            return; /* out of memory */
        }
        printf("  c.s = \"%s\"\n", str);
        (*env)->ReleaseStringUTFChars(env, jstr, str);
    
        jstr = (*env)->NewStringUTF(env, "123");
        if (jstr == NULL) {
            return; /* out of memory */
        }
        (*env)->SetObjectField(env, obj, fid_s, jstr);
    }
    
    • The static variable fid_s stores the precomputed field ID for "InstanceFieldAccess.s".
    • When the InstanceFieldAccess.accessField method is called for the first time, it computes the field ID and caches it in the static variable for later use.
  • Caching in the Defining Class's Initializer
  • If we use "caching at the Point of Use", it runs into some situations (weakness):
    • It incurs a small performance impact on the "fast path" when the IDs have already been cached.
    • It could lead to duplication of caching and checking.
    It is more convenient to initialize the field and method IDs required by a native method before the application can have a chance to invoke the native method.(Improvement)
    • a suitable place for computing and caching field or method IDs is in the static initializer of the class that defines the fields or methods.
    1. (Example) InstanceMethodCall.java: To cache the method ID for InstanceMethodCall.callback(), we introduce a new native method initIDs that called from the static initializer of the InstanceMethodCall class.
    2. class InstanceMethodCall {
          private static native void initIDs();
          private native void nativeMethod();
          private void callback() {
              System.out.println("In Java");
          }
          public static void main(String args[]) {
              InstanceMethodCall c = new InstanceMethodCall();
              c.nativeMethod();
          }
          static {
              System.loadLibrary("InstanceMethodCall");
              initIDs();
          }
      }
      
    3. Regenerate the C native header file (InstanceMethodCall.h):
    4. /* DO NOT EDIT THIS FILE - it is machine generated */                                                             
      #include <jni.h>
      /* Header for class InstanceMethodCall */
      
      #ifndef _Included_InstanceMethodCall
      #define _Included_InstanceMethodCall
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     InstanceMethodCall
       * Method:    initIDs
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_InstanceMethodCall_initIDs
        (JNIEnv *, jclass);
      
      /*
       * Class:     InstanceMethodCall
       * Method:    nativeMethod
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod
        (JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    5. C implementation file (InstanceMethodCall.c):
    6. #include <stdio.h>
      #include <jni.h>
      
      jmethodID MID_InstanceMethodCall_callback;
      
          JNIEXPORT void JNICALL
      Java_InstanceMethodCall_initIDs(JNIEnv *env, jclass cls)
      {
          MID_InstanceMethodCall_callback = (*env)->GetMethodID(env, cls, "callback", "()V");
      }
      
          JNIEXPORT void JNICALL
      Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
      {
          printf("Output: In C code\n");
          (*env)->CallVoidMethod(env, obj, MID_InstanceMethodCall_callback);
      }
      
      • The implementation of initIDs() simply computes and caches the method ID for InstanceMethodCall.callback().
      • The JVM runs the static initializer, and in turn calls the initIDs() method, before executing any other methods in the InstanceMethodCall class. With the method ID is already cached in a global variable, the native implementation of InstanceMethodCall.nativeMethod() no longer needs to perform a symbolic lookup.
      • RUN the InstanceMethodCall:
      • Output: In C code
        Output: In Java code
  • Comparison between the Two Approaches to Caching IDs
    • Caching IDs at the point of use:
      • (Advantage) - The reasonable solution if the JNI programmer does not have control over the source of the class that defines the field or method.
      • (Disadvantage) -
        1. Requires a check in the execution fast path and may also require duplicated checks and initialization of the same field or method ID.
        2. Method and field IDs are only valid until the class is unloaded.
    • Caching in the Defining Class's Initializer:
      • (Advantage) - Caching is done in the static initializer of the defining class, the cached IDs will automatically be recalculated when the class is unloaded and later reloaded.
  • Performance of JNI Field and Method Operations
    • How does the cost of ...
      1. performing a callback from native code (a Native/Java callback)?
      2. calling a native method (a Java/Native call)?
      3. calling a regular method (a Java/Java call)?
      Java/native calls are potentially slower than Java/Java calls for the following reasons:
      • Native methods most likely follow a different calling convention than that used by Java/Java calls inside the Java virtual machine implementation. As a result, the virtual machine must perform additional operations to build arguments and set up the stack frame before jumping to a native method entry point.
      • It is common for the virtual machine to inline method calls. Inlining Java/native calls is a lot harder than inlining Java/Java calls.
      The typical virtual machine may execute a Java/native call roughly two to three times slower than it executes a Java/Java call.
      In theory, the overhead of native/Java callbacks could also be within two to three times of Java/Java calls.

2010年10月6日 星期三

JNI - Invoking Constructors

In the JNI, constructors may be invoked following steps similar to those used for calling instance methods.
    Invoke constructors as following steps:
  1. To obtain the method ID of a constructor, pass "<init>" as the method name and "V" as the return type in the method descriptor.
  2. To invoke the constructor by passing the method ID to JNI functions such as NewObject.
  3. (Example) The following code implements the equivalent functionality of the JNI function NewString, which constructs a java.lang.String object from the Unicode characters stored in a C buffer:
jstring MyNewString(JNIEnv *env, jchar *chars, jint len)
{
    jclass stringClass;
    jmethodID cid;
    jcharArray elemArr;
    jstring result;

    stringClass = (*env)->FindClass(env, "java/lang/String");
    if (stringClass == NULL) {
        return NULL; /* exception thrown */
    }
    /* Get the method ID for the String(char[]) constructor */
    cid = (*env)->GetMethodID(env, stringClass, "<init>", "([C)V");
    if (cid == NULL) {
        return NULL; /* exception thrown */
    }

    /* Create a char[] that holds the string characters */
    elemArr = (*env)->NewCharArray(env, len);
    if (elemArr == NULL) {
        return NULL; /* exception thrown */
    }
    (*env)->SetCharArrayRegion(env, elemArr, 0, len, chars);

    /* Construct a java.lang.String object */
    result = (*env)->NewObject(env, stringClass, cid, elemArr);
 
    /* Free local references */
    (*env)->DeleteLocalRef(env, elemArr);
    (*env)->DeleteLocalRef(env, stringClass);
    return result;
}
  1. FindClass(): returns a reference to the java.lang.String class.
  2. GetMethodID(): returns the method ID for the string constructor, String(char[] chars).
  3. NewCharArray(): to allocate a character array that holds all the string elements.
  4. NewObject(): invokes the constructor specified by the method ID.
  5. DeleteLocalRef(): allows the virtual machine to free the resources used by local references elemArr and stringClass.
It is also possible to invoke constructors using the CallNonvirtualVoidMethod function.
    result = (*env)->NewObject(env, stringClass, cid, elemArr);
  • The single NewObject call above may be replaced by an AllocObject call followed by a CallNonvirtualVoidMethod call:
  • result = (*env)->AllocObject(env, stringClass);
    if (result) {
        (*env)->CallNonvirtualVoidMethod(env, result, stringClass, cid, elemArr);
        /* we need to check for possible exceptions */
        if ((*env)->ExceptionCheck(env)) {
            (*env)->DeleteLocalRef(env, result);
            result = NULL;
        }
    }
    
    AllocObject(): creates an uninitialized object.
    CallNonvirtualVoidMethod(): invokes constructors.
    In most cases, however, you should use NewObject and avoid the more error-prone AllocObject/CallNonvirtualVoidMethod pair.

2010年10月4日 星期一

JNI - Access Instance (object) / Static (class) Method

There are several kinds of methods in the Java programming language.
  • (Object) Instance methods must be invoked on a specific instance of a class.
  • (Class) Static methods may be invoked independent of any instance.
  • Calling Instance Methods
  • (Example) InstanceMethodCall.java: a native method that in turn calls an instance method implemented in the Java programming language.
    1. InstanceMethodCall.java
    2. class InstanceMethodCall {
          private native void nativeMethod();
          private void callback() {
              System.out.println("Output: In Java code");
          }
          public static void main(String args[]) {
              InstanceMethodCall c = new InstanceMethodCall();
              c.nativeMethod();
          }
          static {
              System.loadLibrary("InstanceMethodCall");
          }
      }
      
    3. Generate C header file: InstanceMethodCall.h
    4. /* DO NOT EDIT THIS FILE - it is machine generated */                                                    
      #include <jni.h>
      /* Header for class InstanceMethodCall */
      
      #ifndef _Included_InstanceMethodCall
      #define _Included_InstanceMethodCall
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     InstanceMethodCall
       * Method:    nativeMethod
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod
        (JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    5. C implementation of InstanceMethodCall.c
    6. #include <stdio.h>
      #include <jni.h>
      
      JNIEXPORT void JNICALL 
       Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
       {
           jclass cls = (*env)->GetObjectClass(env, obj);
           jmethodID mid = 
               (*env)->GetMethodID(env, cls, "callback", "()V");
           if (mid == NULL) {
               return; /* method not found */
           }
           printf("Output: In C code\n");
           (*env)->CallVoidMethod(env, obj, mid);
       }
      
        Two steps required to call an instance method:
      1. GetMethodID performs a lookup for the method in the given class. The lookup is based on the name and type descriptor of the method. If the method does not exist, GetMethodID returns NULL and causes a NoSuchMethodError to be thrown in the code.
      2. CallVoidMethod invokes an instance method that has the return type void. You pass the object, the method ID, and the actual arguments to CallVoidMethod.
    7. Generate the shared library file - libInstanceMethodCall.so
    8. gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux InstanceMethodCall.c -o libInstanceMethodCall.so
    9. RUN InstanceMethodCall output:
    10. Output: In C code
      Output: In Java code

  • Calling Static Methods
  • Similarly, we can perform callbacks to static methods from native code by following steps:
    • Obtain the method ID using GetStaticMethodID, as opposed to GetMethodID.
    • Pass the class, method ID, and arguments to one of the family of static method invocation functions: CallStaticVoidMethod, CallStaticBooleanMethod, and so on.
      (Example) StaticMethodCall.java: a slight variation of the earlier InstanceMethodCall example
    1. StaticMethodCall.java
    2. class StaticMethodCall {
          private native void nativeMethod();
          private static void callback() {
              System.out.println("Output: In Java code");
          }
          public static void main(String args[]) {
              StaticMethodCall c = new StaticMethodCall();
              c.nativeMethod();
          }
          static {
              System.loadLibrary("StaticMethodCall");
          }
      }
      
    3. Generate C header file: StaticMethodCall.h
    4. /* DO NOT EDIT THIS FILE - it is machine generated */                           
      #include <jni.h>
      /* Header for class StaticMethodCall */
      
      #ifndef _Included_StaticMethodCall
      #define _Included_StaticMethodCall
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     StaticMethodCall
       * Method:    nativeMethod
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_StaticMethodCall_nativeMethod
        (JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    5. C implementation of StaticMethodCall.c
    6. #include <stdio.h>
      #include <jni.h>
                                                                                      
          JNIEXPORT void JNICALL
      Java_StaticMethodCall_nativeMethod(JNIEnv *env, jobject obj)
      {
          jclass cls = (*env)->GetObjectClass(env, obj);
          jmethodID mid =
              (*env)->GetStaticMethodID(env, cls, "callback", "()V");
          if (mid == NULL) {
              return;  /* method not found */
          }
          printf("Output: In C code\n");
          (*env)->CallStaticVoidMethod(env, cls, mid);
      }
      
    7. Generate the shared library file - libStaticMethodCall.so
    8. gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux StaticMethodCall.c -o libStaticMethodCall.so
    9. RUN StaticmethodCall output:
    10. Output: In C code
      Output: In Java code

  • JNI Method Descriptors
    • similar to how descriptor denotes field types
    • Format:('[' + ARGUMENT_TYPE) + RETURN_TYPE
    • For example:
      native private String getLine(String);
      "(Ljava/lang/String;)Ljava/lang/String;"
      public static void main(String[] args);
      "([Ljava/lang/String;)V"
    • Use the javap tool to print out JNI method descriptors.
    • For example: javap -s -p InstanceMethodCall
    • -s: to output JNI descriptor strings rather than types as they appear in the Java programming language
    • -p: to include information about the private members of the class
    • The output:
      Compiled from "InstanceMethodCall.java"
      class InstanceMethodCall extends java.lang.Object{
      InstanceMethodCall();
        Signature: ()V
      private native void nativeMethod();
        Signature: ()V
      private void callback();
        Signature: ()V
      public static void main(java.lang.String[]);
        Signature: ([Ljava/lang/String;)V
      static {};
        Signature: ()V }

JNI - Access Instance (object) / Static (class) Field

Fields Accessing
  • 這個方法的觀念很簡單,就是:既然java native function是屬於某一個class,理論上它就可以存取這個class裡所有的member fields。因此,這個class中所有的函式,無論在java還是C++,都可以對同一組資料做存取而無需透過參數傳遞。
    The Java programming language supports two kinds of fields.
    1. (Object) Each instance of a class has its own copy of the instance fields of the class.
    2. (Class) All instances of a class share the static fields of the class.
    3. The JNI provides functions that native code can use to get and set instance fields in objects and static fields in classes.
  • Access Object Fileds
  • (Example) InstanceFieldAccess.java: The main method creates an object, sets the instance field, and then calls the native method (InstanceFieldAccess.accessField) to print out the existing value of the instance field and then set the field to a new value.
    1. InstanceFieldAccess.java
    2. class InstanceFieldAccess {
          private String s;
          private native void accessField();
      
          public static void main(String args[]) {
              InstanceFieldAccess c = new InstanceFieldAccess();
              c.s = "abc";
              c.accessField();
              System.out.println("In Java:");
              System.out.println("  c.s = \"" + c.s + "\"");
          }
          static {
              System.loadLibrary("InstanceFieldAccess");
          }
      }
      
    3. Generate C header file: InstanceFieldAccess.h
    4. /* DO NOT EDIT THIS FILE - it is machine generated */                                                        
      #include <jni.h>
      /* Header for class InstanceFieldAccess */
      
      #ifndef _Included_InstanceFieldAccess
      #define _Included_InstanceFieldAccess
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     InstanceFieldAccess
       * Method:    accessField
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField
        (JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    5. C implementation of InstanceFieldAccess.c
    6. #include <stdio.h>
      #include <jni.h>
      
          JNIEXPORT void JNICALL 
      Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
      {
          jfieldID fid;   /* store the field ID */
          jstring jstr;
          const char *str;
      
          /* Get a reference to obj's class */
          jclass cls = (*env)->GetObjectClass(env, obj);
      
          printf("In C:\n");
      
          /* Look for the instance field s in cls */
          fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
          if (fid == NULL) {
              return; /* failed to find the field */
          }
      
          /* Read the instance field s */
          jstr = (*env)->GetObjectField(env, obj, fid);
          str = (*env)->GetStringUTFChars(env, jstr, NULL);
          if (str == NULL) {
              return; /* out of memory */
          }
          printf("  c.s = \"%s\"\n", str);
          (*env)->ReleaseStringUTFChars(env, jstr, str);
      
          /* Create a new string and overwrite the instance field */
          jstr = (*env)->NewStringUTF(env, "123");
          if (jstr == NULL) {
              return; /* out of memory */
          }
          (*env)->SetObjectField(env, obj, fid, jstr);
      }
      
        To access an instance field, the native method follows a two-step process.
      1. First, it calls GetFieldID to obtain the field ID from the class reference, field name, and field descriptor:
      2. fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
        
      3. Once you have obtained the field ID, you can pass the object reference and the field ID to the appropriate instance field access function (ex. GetObjectField):
      4. jstr = (*env)->GetObjectField(env, obj, fid);
        
        P.S. Strings & Arrays (special objects) : use GetObjectField to access the instance fields.
               Primitive types : use GetIntField and SetFloatField for accessing instance fields.
    7. Generate shared library file - libInstanceFieldAccess.so
    8. gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux InstanceFieldAccess.c -o libInstanceFieldAccess.so
    9. RUN InstanceFieldAccess output:
    10. In C: c.s = "abc"
      In Java: c.s = "123"
  • Access Static Fields
    1. Accessing static fields is similar to accessing instance fields.
      (Example) StaticFielcdAccess.java: The main method creates an object, initializes the static field, and then calls the native method (StaticFieldAccess.accessField) to print out the existing value of the static field and then set the field to a new value.
    2. StaticFielcdAccess.java
    3. class StaticFieldAccess {
          private static int si;
          private native void accessField();
      
          public static void main(String args[]) {
              StaticFieldAccess c = new StaticFieldAccess();
              StaticFieldAccess.si = 100;
              c.accessField();
              System.out.println("In Java:");
              System.out.println("  StaticFieldAccess.si = " + si);
          }
          static {
              System.loadLibrary("StaticFieldAccess");
          }
      }
      
    4. Generate c header file: StaticFielcdAccess.h
    5. /* DO NOT EDIT THIS FILE - it is machine generated */                           
      #include <jni.h>
      /* Header for class StaticFieldAccess */
      
      #ifndef _Included_StaticFieldAccess
      #define _Included_StaticFieldAccess
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     StaticFieldAccess
       * Method:    accessField
       * Signature: ()V
       */
      JNIEXPORT void JNICALL Java_StaticFieldAccess_accessField
        (JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    6. C implementation of StaticFieldAccess.c
    7. #include <stdio.h>
      #include <jni.h>
      
      JNIEXPORT void JNICALL 
      Java_StaticFieldAccess_accessField(JNIEnv *env, jobject obj)
      {
          jfieldID fid;   /* store the field ID */
          jint si;
      
          /* Get a reference to obj's class */
          jclass cls = (*env)->GetObjectClass(env, obj);
      
          printf("In C:\n");
      
          /* Look for the static field si in cls */
          fid = (*env)->GetStaticFieldID(env, cls, "si", "I");
          if (fid == NULL) {
              return; /* field not found */
          }
          /* Access the static field si */
          si = (*env)->GetStaticIntField(env, cls, fid);
          printf("  StaticFieldAccess.si = %d\n", si);
          (*env)->SetStaticIntField(env, cls, fid, 200);
      }
      
    8. Generate shared library file - libStaticFieldAccess.so
    9. gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux StaticFieldAccess.c -o libStaticFieldAccess.so
    10. RUN StaticFieldAccess output:
    11. In C: StaticFieldAccess.si = 100
      In Java: StaticFieldAccess.si = 200
    There are two differences between how access a static field and how access an instance field:
    • Usage: call GetStaticFieldID for static fields, as opposed to GetFieldID for instance fields. GetStaticFieldID and GetFieldID have the same return type jfieldID.
    • Once you have obtained the static field ID, you pass the class reference, as opposed to an object reference, to the appropriate static field access function (such as GetStaticIntField for static int field).
  • JNI Field Descriptors
    • The specially encoded C string "Ljava/lang/String;" to represent a field type (such as java.lang.String) in the Java programming language. These C strings are called JNI field descriptors.
    • Descriptors Query Tool: "javap" tool (shipped with JDK or Java 2 SDK releases) to generate the field descriptors from class files.
    • javap -s -p CLASS_NAME
      • -s option: print internal type signatures
      • -p option: exposing private members