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

getResourceString() returns signing error, workaround flawed

XMLWordPrintable

    • x86
    • other

      FULL PRODUCT VERSION :
      Reproduced on Java 8, 131, 161, and Java 9.0.4

      ADDITIONAL OS VERSION INFORMATION :
      Not OS specific, reproduced on Windows 10, Windows 7, Linux Ubuntu 12.04, etc.

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      To manifest the bug, temporary files (caching) must be enabled in the java control panel.

      Note: works fine with caching disabled.


      A DESCRIPTION OF THE PROBLEM :
      When running a Java Web Start application with caching (temporary files) disabled in the control panel, code using getResourceAsStream() works as advertised. When caching is enabled, a jar signing exception (Java 9) or a null stream is returned (Java 8) on the getResourceAsStream() calls.

      The behaviour of an application should not vary between working and failing with Java caching (temporary files) enable/disable.

      A faulty workaround is documented in 81544509. Use .getResouce().openStream() in place of .getResourceAsStream(). Nothing is noted about the problem only occurring when caching is enabled.

      This workaround is flawed. The client will operate, but only after the VM re-contacts the OCS (Original Content Server) for looking for updates of the jar. It is by design that getResourceAsStream() only uses the Local jars, does not contact the OCS, but getResource() will always attempt to acquire a fresh copy from the OCS (Java bugs 4668479, 4805170, 4507227), so that if a newer version of the resource (like a stock tick update) is available it will be used. This is silly behaviour for content of a jar file, but it remains as per design.

      We already ran into issues with getResource() and getResourceAsString(), hence detailed knowledge of Java bugs 4668479, 4805170, 4507227. We are unable to have a viable solution without operating getResourceAsString(). Slow links, large jar files, and a large quantity of embedded image resources (UI icons) make getResource() unworkable.

      Doing a getResource() on a large jar can cause serious performance impacts in the client application when multiple resources are needed from the jar. Each getResource() call does an independent OCS resource request. This may result in the jar being downloaded each time. I don't know what happens when running in offline mode, but I suspect it cannot be good.

      When jar versioning is added to JNLP, (see jnlp.versionEnabled, property of resouces in JNLP file), the problem gets different. The update request to the OCS server does not include the version details (expected as query parameters on get url). Since the server is only returning the jars whose names are qualified by the version, the unqualified name is an unresolved resource.

      In all cases the client runs with the workaround, but the performance can be dramatically effected, for our application, the solution is unviable.


      REGRESSION. Last worked in version 6u43

      ADDITIONAL REGRESSION INFORMATION:
      Problems similar to or identical with resource acquisition using getResourceAsStream() have been reported since Java 1.3. Speficially the null returns for the stream. Most (all?) reports are closed as resolved. Some involve real fixes. It would seem that this use case worked at one time.

      Also because it works with caching disabled, that would suggest that it should also work with caching enabled, making treating this bug as a "regression" appropriate.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      To enable/disable temporary files (caching) goto Java control panel, general tab, settings button.

      1. Compile and deploy to server the included source.
      2. Launch java web start with temporary files disabled in java control panel.
      3. Notice "Success!!!" on java console.
      4. Launch java web start with temporary files enabled in java control panel.
      5. Notice a signing exception.

      Addtional demonstration
      6. Comment out the line using getResourceAsStream()
      7. Uncomment the line using openStream().
      8. Disable caching (temporary files).
      9. Recompile.
      10. Sniff network.
      11. Launch application.
      12. Notice Success!!! on java console
      13.Notice the client contacted the OCS again!
      14. If do more getResource() calls, there will be more OCS contacts. Each may result in the jar being delivered again based upon caching settings.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Step 5: Success instead of exception

      For a viable workaround:
      Step 13 and 14: No extra calls to OCS.
      ACTUAL -
      As per Steps in reproduction.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Bug may manifest as a jar signing exception (java 9) or as a null pointer exception (Java 8) when the stream comes back null. Here is the Java 8 proof (line numbers may not match to provided demo source.)

      java.lang.NullPointerException
      at com.dfielder.bug.JarReadingCachingBasedBug.<init>(JarReadingCachingBasedBug.java:15)
      at com.dfielder.bug.JarReadingCachingBasedBug.main(JarReadingCachingBasedBug.java:8)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at com.sun.javaws.Launcher.executeApplication(Unknown Source)
      at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
      at com.sun.javaws.Launcher.doLaunchApp(Unknown Source)
      at com.sun.javaws.Launcher.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      You will have to put this in your favourite JNLP deployment environment, with your own certificates. To see the jar signing variant from Java 9, I believe you cannot use a site exception, you must use real certificates with registered root.

      import java.io.IOException;
      import java.io.InputStream;
      public class JarReadingCachingBasedBug {
      public static void main(String[] args) throws IOException {
      new JarReadingCachingBasedBug();
      }
      public JarReadingCachingBasedBug() throws IOException {
      System.out.println("Trying");
      InputStream resourceStream = getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
      //Documented workaround. Causes re-request of jar from OCS (Orginal content server).
      //InputStream resourceStream = getClass().getClassLoader().getResource("META-INF/MANIFEST.MF").openStream();
      System.out.println(resourceStream.read());
      System.out.println("Success!!!");
      }
      }

      Substitute 2 instances of <replace here>

      <?xml version="1.0" encoding="UTF-8"?>
      <jnlp spec="1.0+" codebase="https://&lt;replace here>" href="OracleBug.jnlp">
          <information>
              <title>OracleBug</title>
              <vendor>Bug dude</vendor>
              <offline-allowed/>
          </information>
          <security>
      <all-permissions/>
      </security>
          <resources>
              <!-- Application Resources -->
              <j2se version="1.8+" href="http://java.sun.com/products/autodl/j2se"/>
              <jar href="OracleBug.jar" main="true" version="14"/>
              <property name="jnlp.versionEnabled" value="true"/>
          </resources>
          <application-desc name="VR" main-class="<replace here>.JarReadingCachingBasedBug">
          </application-desc>
      </jnlp>
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      As per above: Workaround in 81544509 does not work because it forces a call back to the OCS.

      Only real workaround is to disable the caching, which is a critical problem for our customers because our solution has many large jars, making launch time incredably slow.

            herrick Andy Herrick (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: