Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6569899

Conflict between jni.h and JNI specification

XMLWordPrintable

    • b133
    • generic
    • generic
    • Verified

      1) NewObjectA, Call<type>MethodA,CallNonvirtual<type>MethodA and CallStatic<type>MethodA
      specification contains: "jvalue *args" whereas
      jni.h contains "const jvalue *args".
      personally favor the latter as const is safer and believe making this
      change in the specification would also be backwards compatible.

      2)GetStringUTFChars:

      specification: const jbyte* GetStringUTFChars(JNIEnv *env, jstring
                     string, jboolean *isCopy);

      jni.h: const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring
             str, jboolean *isCopy);

      The return type is different. Don't know about other platforms, but
      under Windows we obviously favor the jni.h version of using char*. In
      fact, this should probably be "const jchar*" in both jni.h and the
      specification.

      3) ArrayRegion:
      Specification contains "void Set<PrimitiveType>ArrayRegion(JNIEnv
                              *env, ArrayType array,jsize start, jsize len, NativeType *buf);"
      jni.h contains "const NativeType *buf".
      Personally favor the jni.h version (you should probably apply this
      to all setter methods in the specification).

      4) ToFeflectedMethod:
      Specification contains "jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID);"
      jni.h contains "jobject (JNICALL *ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID,
                      jboolean isStatic);"

      the same is true for the "ToReflectedField" method.
      This is a rather huge mismatch. An entire argument is missing! I assume
      that the jni.h version is the correct one and the specification should
      be updated?

      5) JNI_CreateJavaVM:
      Specification contains "jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args);"
      jni.h contains "_JNI_IMPORT_OR_EXPORT_jint JNICALL JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);"

      The error shows up for "AttachCurrentThread".
      A compiler error results if the wrong type is used. I personally favor
      the specification on this one, we should be using JNIEnv** not void**.

      6) AttachCurrentThreadAsDaemon:
      AttachCurrentThreadAsDaemon now uses void** for penv in both the
      specification and jni.h but I would argue it should use JNIEnv** as
      well. It's own documentation starts up by saying "Same semantics as
      AttachCurrentThread" so people would expect them to work the same.

      7) AttachCurrentThread:
      The JNI specification clearly states the following function prototype:
       
        jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args);
        (Source:
        http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp1060)

        Yet if you try using jni.h as deployed in Sun's JDK the actual prototype is:
       
        jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
        (notice penv changed from JNIEnv** to void**).

      This is a major concern because I believe this makes it impossible to
      write portable code against the two variants. Specifically we have one
      customer whose JDK uses JNIEnv** while Sun's uses void** and if you code
      the wrong type you will end up with a compiler error. I tend to believe
      that JNIEnv** is the correct prototype and that there is a bug in Sun's
      jni.h.

      Please clarify what developers are supposed to do in this situation?

            kamg Keith Mcguigan (Inactive)
            tyao Ting-Yun Ingrid Yao (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: