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

JNI: Clarify specification w.r.t. class loading, linking and initialization

    Details

    • Type: Enhancement
    • Status: Closed
    • Priority: P4
    • Resolution: Won't Fix
    • Affects Version/s: 14
    • Fix Version/s: tbd
    • Component/s: hotspot
    • Labels:

      Description

      JNI specification in its current shape isn't clear enough about when class
      initialization checks are performed. It led to the situation when current
      implementation significantly diverges from bytecode behavior (mandated by JVMS)
      which cause problems both from user and implementation perspectives.

      From a user perspective, it's hard to write correct code in presence of recursive initialization, multi-threaded accesses, and possibility of initialization failure. The only way to check that current thread is the initializing thread or notice a failure using JNI is to repeat jmethodID/jfieldID resolution. And bugs lead to accesses into partially initialized classes or classes in error state.

      From implementation perspective, difference between JNI & bytecode behavior complicates implementation in the JVM.

      Some details:

      JVMS-5.5 enumerates all the scenarios when class initialization happens. Among them:
          * The execution of any one of the Java Virtual Machine instructions new,
      getstatic, putstatic, or invokestatic that references C (§new, §getstatic,
      §putstatic, §invokestatic).

          * Upon execution of a new instruction, the class to be initialized is the class referenced by the instruction.

          * Upon execution of a getstatic, putstatic, or invokestatic instruction, the
      class or interface to be initialized is the class or interface that declares
      the resolved field or method.

      JNI specification:
      GetStaticFieldID
          GetStaticFieldID() causes an uninitialized class to be initialized.
          THROWS: ExceptionInInitializerError: if the class initializer fails due to an exception.

      GetStatic<type>Field Routines
      SetStatic<type>Field Routines
          Oblivious of class initialization.

      GetFieldID
          GetFieldID() causes an uninitialized class to be initialized.
          THROWS: ExceptionInInitializerError: if the class initializer fails due to an exception.

      GetStaticMethodID
          GetStaticMethodID() causes an uninitialized class to be initialized.
          THROWS: ExceptionInInitializerError: if the class initializer fails due to an exception.

      CallStatic<type>Method Routines
      CallStatic<type>MethodA Routines
      CallStatic<type>MethodV Routines
          Oblivious of class initialization.

      GetMethodID
          GetMethodID() causes an uninitialized class to be initialized.
          THROWS: ExceptionInInitializerError: if the class initializer fails due to an exception.

      AllocObject
          Oblivious of class initialization.

      NewObject, NewObjectA, NewObjectV
          Oblivious of class initialization.

      Current implementation behavior:
         * GetStaticFieldID and GetStaticMethodID perform class initialization check

         * (Get|Set)Static<type>Field and CallStatic<type>Method* don't have the check

         * AllocObject and NewObject* perform the check

      Update:

      The problem is more extensive than just initialization, the specification is also unclear when it comes to the different steps of loading and linking a class prior to initialization. So methods have to allow for LinkageErrors as well as those pertaining to class initialization. Basically any method that takes a reference to a Class instance should state what affect it has on the linking and initialization state of that class.

      Also note that it is possible for instances of a class to escape even if a class fails initialization and is marked as erroneous. These instances can then be operated on, and the result of that must consistent with what happens at the Java or bytecode level. There is a risk that we do not obey the basic exception rule that "In all other cases, a non-error return value guarantees that no exceptions have been thrown."

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              vlivanov Vladimir Ivanov
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: