Replace ClassLoader use of finalizer with phantom reference to unload native library

XMLWordPrintable

    • Type: CSR
    • Resolution: Withdrawn
    • Priority: P3
    • None
    • Component/s: core-libs
    • None
    • behavioral
    • medium
    • Hide
      There are two behavioral changes. First, this change may affect the timing on when a native library is being unloaded because it is now handled by the system cleaner thread rather than the finalizer thread that is subject to the thread scheduling. Note that it is unspecified when a native library is unloaded. This behavior is solely implementation-dependent. The native library will be unloaded when a class loader becomes phantom reachable and the cleaner thread is in action to invoke the cleaning method. Previously, the native library will be unloaded when a class loader becomes finalizable and the finalizer thread is in action to invoke the finalizer. It is expected that this behavioral change should not be noticeable except the native library is being reloaded immediately when the class loader is GC'ed before the system cleaner thread gets a chance to handle the unloading of that class loader.

      Second, JNI_OnUnload calling JNI_FindClass can only find classes visible to the system class loader or its ancestor. Existing native library expects to find classes defined to this unloaded class loader or its ancestors that is not a built-in class loader will no longer work. It is specified in the spec for JNI_OnUnload that the programmer should be conservative on using Java VM services, and refrain from arbitrary Java call-backs.

      It is believed that the compatibility risk should be low but marked as medium because it is uncertain how existing applications depend on these behaviors.
      Show
      There are two behavioral changes. First, this change may affect the timing on when a native library is being unloaded because it is now handled by the system cleaner thread rather than the finalizer thread that is subject to the thread scheduling. Note that it is unspecified when a native library is unloaded. This behavior is solely implementation-dependent. The native library will be unloaded when a class loader becomes phantom reachable and the cleaner thread is in action to invoke the cleaning method. Previously, the native library will be unloaded when a class loader becomes finalizable and the finalizer thread is in action to invoke the finalizer. It is expected that this behavioral change should not be noticeable except the native library is being reloaded immediately when the class loader is GC'ed before the system cleaner thread gets a chance to handle the unloading of that class loader. Second, JNI_OnUnload calling JNI_FindClass can only find classes visible to the system class loader or its ancestor. Existing native library expects to find classes defined to this unloaded class loader or its ancestors that is not a built-in class loader will no longer work. It is specified in the spec for JNI_OnUnload that the programmer should be conservative on using Java VM services, and refrain from arbitrary Java call-backs. It is believed that the compatibility risk should be low but marked as medium because it is uncertain how existing applications depend on these behaviors.

      Summary

      Convert the ClassLoader implementation from its use of finalizer to phantom reference to handle unloading of a native library when a class loader is unloaded.

      Problem

      The finalization mechanism is inherently problematic and the JDK implementation should migrate away from its use of finalizers.

      Solution

      Use java.lang.ref.Cleaner to register the class loader and the action to unload a native library.

      Specification

      • JNI_FindClass
      Specify that `JNI_FindClass` uses the system class loader as its context for finding
      class when `JNI_FindClass` is called from `JNI_OnUnload` or `JNI_OnUnload_L`.
      
      This is behavioral change because the hotspot implementation has been using
      the class loader associated with the native library as the current context.  It is 
      a bug because the spec of `JNI_OnUnload` specifies that it is called in an 
      unknown context (such as from a finalizer).
      

      <p>

      • JNI_OnUnload and JNI_OnUnload_L

      Change the spec as follows to reflect that the native library may be unloaded after the class loader is GC'ed.

      <pre>
      

      -Optional function defined by dynamically linked libraries. The VM calls -JNI_OnUnload when the class loader containing the native library is garbage -collected. +Optional function defined by dynamically linked libraries. +When the class loader containing the native library is garbage collected, +the VM registers JNI_OnUnload to be invoked when the native library +is being unloaded. It is not specified when the JNI_OnUnload function +is invoked and the native library is unloaded. </pre>

      <pre>
      

      -Optional function defined by statically linked libraries. When the class loader -containing a statically linked native library 'L' is garbage collected, the VM -will invoke the JNI_OnUnload_L function of the library if such a function is -exported. +Optional function defined by statically linked libraries. +When the class loader containing a statically linked native library 'L' +is garbage collected, the VM registers JNI_OnUnload_L to be invoked +if such a function is exported. It is not specified when the +JNI_OnUnload_L function is invoked.

      </pre>

            Assignee:
            Mandy Chung (Inactive)
            Reporter:
            Mandy Chung (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: