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

AudioClip.play crash on mac with jarloader

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • jfx26
    • jfx24
    • javafx
    • None

      When an mp3 resource is played with AudioClip.play on mac, and the resource is located in a JAR, a crash may occur.

      Example snippet:
      ```
      String source = MainApp.class.getResource(audioFile).toExternalForm();
      AudioClip clip = new AudioClip(source);
      clip.play();
      ```

      The root cause for this seems to be a wrong object being passed in the native layer.
      In its constructor,

      `com/sun/media/jfxmediaimpl/platform/osx/OSXMediaPlayer.java`
      will invoke

      `osxCreatePlayer(mediaLocator, mediaLocator.getContentType(),
                      mediaLocator.getContentLength());`

      which is defined as
      `private native void osxCreatePlayer(Locator locator, String contentType, long sizeHint)`

      Hence, a Locator instance is passed to the native peer (at OSXMediaPlayer.mm) where it is used in
      `JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxCreatePlayer
          (JNIEnv *env, jobject playerObject, jobject jLocator, jstring jContentType, jlong jSizeHint)`

      That jLocator object is used inside the function for doing Locator-related work indeed, but in case of a jar or jrt scheme, it is also passed to `CJavaInputStreamCallbacks->Init` via

      ```
      CJavaInputStreamCallbacks *callbacks = new (nothrow) CJavaInputStreamCallbacks();
              if (!callbacks->Init(env, jLocator)) {
      ```

      The problem is that the latter expects a `ConnectionHolder` and not a `Locator`, as can be seen from
      JavaInputStreamCallbacks.cpp:

      `bool CJavaInputStreamCallbacks::Init(JNIEnv *env, jobject jConnectionHolder)`

      The Init method sets the methodIDs that will be invoked when needed, and it calculates them using the ConnectionHolder class, e.g.:
      `jclass klass = env->FindClass("com/sun/media/jfxmedia/locator/ConnectionHolder");`

      m_ReadNextBlockMID = env->GetMethodID(klass, "readNextBlock", "()I");`

      But when those methods are invoked, the Locator object from the OSXMediaPlayer is used instead of the ConnectionHolder that belongs to the Locator.

            almatvee Alexander Matveev
            jvos Johan Vos
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: