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

JVMPI access from JNI GetEnv inconsistent with JNI

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 1.4.0
    • 1.3.1, 1.4.0
    • vm-legacy
    • beta3
    • generic, sparc
    • generic, solaris_8
    • Verified


      When you ask a a VM that supports JNI 1.2 for
      JNI 1.1 you get back JNI 1.2 - that includes not just the function
      table (aka interface structure) but also what version it reports
      itself as being - it will tell you it is JNI 1.2 (code below).
      By comparison, when you ask a VM that supports JVMPI 1.1 for
      JVMPI 1 you get back JVMPI 1 (version field and function table).

      To summarize:
      JNI choose - 2) always newest
      JVMPI choose - 1) exact match

      Since GetEnv is a JNI function, JNI should define its action. This
      is an incompatibility.

      Additionally, note that the JVMPI spec:

              http://java.sun.com/j2se/1.3/docs/guide/jvmpi/jvmpi.html

      describes compatibility not exact match:

        The GetEnv function returns a pointer to a JVMPI_Interface whose version field
        indicates a JVMPI version that is compatible to the version number argument
        passed in the GetEnv call. Note that the value of the version field is not
        necessarily identical to the version argument passed in the GetEnv call.

      Thus it is also an incompatibility with the JVMPI spec.

      ============================ Code ========================

      ---- HotSpot GetEnv ----

      jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
        Thread* thread = ThreadLocalStorage::thread();
        if (thread != NULL && thread->is_Java_thread()) {
          if (version == JNI_VERSION_1_1 || version == JNI_VERSION_1_2) {
            *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment();
            return JNI_OK;
          } else if (version == JVMPI_VERSION_1 || version == JVMPI_VERSION_1_1) {
            *penv = (void* )jvmpi::GetInterface_1(version); // version 1.X support
            return JNI_OK;
          } else if (version == JVMDI_VERSION_1) {
            *penv = (void *)jvmdi::GetInterface_1(vm);
            return JNI_OK;
          } else {
            *penv = NULL;
            return JNI_EVERSION;
          }
        } else {
          *penv = NULL;
          return JNI_EDETACHED;
        }
      }

      ---- partial original Classic GetEnv ----

      static jint JNICALL
      jni_GetEnv(JavaVM *vm, void **penv, jint version)
      {
          sys_thread_t *self = sysThreadSelf();
          if (self) {
              if (version == JNI_VERSION_1_1 || version == JNI_VERSION_1_2) {
                  *penv = (void *)EE2JNIEnv(SysThread2EE(self));
                  return JNI_OK;
      ...


      ---- HotSpot JNI GetVersion ----

      JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))
        JNIWrapper("GetVersion");
        return JNI_VERSION_1_2;
      JNI_END

      ---- HotSpot partial JVMPI initialize ----

      void jvmpi::initialize(int version) {
      ....
        jvmpi_interface.GetMethodClass = &get_method_class;

        if (version == JVMPI_VERSION_1) {
          jvmpi_interface.jobjectID2jobject = NULL;
          jvmpi_interface.jobject2jobjectID = NULL;
        } else { // JVMPI_VERSION_1_1 and beyond
          jvmpi_interface.jobjectID2jobject = &jobjectID_2_jobject;
          jvmpi_interface.jobject2jobjectID = &jobject_2_jobjectID;
        }
      }

      ---- HotSpot partial JVMPI initialize ----

      JVMPI_Interface* jvmpi::GetInterface_1(int version) {
        initialize(version);
        return &jvmpi_interface;
      }

            dcubed Daniel Daugherty
            rfield Robert Field (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: