0 Replies Latest reply: Sep 25, 2013 3:03 PM by uinerd RSS

    Workaround for 7u25 7u40 6u51 RMI invokeLater() / invokeAndWait() AppContext NPE bug (JDK-8019274)

    uinerd

      // Here is the workaround, packaged in a utility class. (You'll need to

      // include the jnlp.jar in your project.)

      //

      // Replace all your calls to invokeLater() and invokeAndWait() with

      // JreFix.invokeNowOrLater() and JreFix.invokeNowOrWait().

      //

      // It's not a perfect solution, but if your web start app is offline because

      // of JDK-8019274, this should get it running again.

      //

      // uinerd, RTP, NC

       

      package com.uinerd;

       

      import java.awt.Component;

      import java.lang.reflect.Field;

      import java.util.Map;

       

      import javax.jnlp.BasicService;

      import javax.jnlp.IntegrationService;

      import javax.jnlp.ServiceManager;

      import javax.jnlp.UnavailableServiceException;

      import javax.swing.JLabel;

      import javax.swing.JOptionPane;

      import javax.swing.SwingUtilities;

       

      import sun.awt.AppContext;

       

      /**

      * Encapsulates the Java 7u25/7u40/6u51 hack

      */

      public class JreFix {

          private static String badVersionInfo = null;

          private static AppContext awtEventDispatchContext = null;

          private static AppContext mainThreadContext = null;

       

          private static Boolean isWebStart = null;

          private static BasicService basicService = null;

          private static IntegrationService integrationService = null;

       

          /**

           * Call this early in main(). Do not call this using an invoke* method.

           */

          public static void init() {

              if (isWebstart() && isApplicableJvmType()) {

                  String javaVersion = System.getProperty("java.version");

                 

                  if ("1.7.0_25".equals(javaVersion)) {

                      badVersionInfo = "7u25";

                  }

                  else if ("1.7.0_40".equals(javaVersion)) {

                      badVersionInfo = "7u40";

                  }

                  else if (javaVersion != null && "1.6.0_51".equals(javaVersion.substring(0,8))) {

                      badVersionInfo = "6u51";

                  }

                  else if ("javaws-10.25.2.16".equals(System.getProperty("javawebstart.version"))) {

                      badVersionInfo = "Web Start 10.25.2.16";

                  }

              }

             

              if (badVersionInfo != null) {

                  mainThreadContext = AppContext.getAppContext();

                  try {

                      SwingUtilities.invokeAndWait(new Runnable() {

                          public void run() {

                              awtEventDispatchContext = AppContext.getAppContext();

                          }

                      });

                  }

                  catch (Exception e) {

                      displayErrorAndExit(null);

                  }

             

                  if (mainThreadContext == null || awtEventDispatchContext == null) {

                      displayErrorAndExit(null);

                  }

              }

          }

         

          public static void invokeNowOrLater(Runnable runnable) {

              if (hasAppContextBug()) {

                  invokeLaterOnAwtEventDispatchThreadContext(runnable);

              }

              else {

                  if (SwingUtilities.isEventDispatchThread()) {

                      runnable.run();

                  }

                  else {

                      SwingUtilities.invokeLater(runnable);

                  }

              }

          }

             

          public static void invokeNowOrWait(Runnable runnable) {

              if (hasAppContextBug()) {

                  fixThreadAppContext(null);

              }

               

              if (SwingUtilities.isEventDispatchThread()) {

                  runnable.run();

              }

              else {

                  try {

                      SwingUtilities.invokeAndWait(runnable);

                  }

                  catch (Exception e) {

                      // handle it

                  }

              }

          }

                 

          public static boolean hasAppContextBug() {

              return isJreWithAppContextBug() && AppContext.getAppContext() == null;

          }

       

          public static void invokeLaterOnAwtEventDispatchThreadContext(Runnable runnable) {

              sun.awt.SunToolkit.invokeLaterOnAppContext(awtEventDispatchContext, runnable);

          }

       

          public static void fixThreadAppContext(Component parent) {

              try {

                  final Field field = AppContext.class.getDeclaredField("threadGroup2appContext");

                  field.setAccessible(true);

                  Map<ThreadGroup, AppContext> threadGroup2appContext = (Map<ThreadGroup, AppContext>)field.get(null);

                  final ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();

                  threadGroup2appContext.put(currentThreadGroup, mainThreadContext);

              }

              catch (Exception e) {

                  displayErrorAndExit(parent);

              }

             

              if (AppContext.getAppContext() == null) {

                  displayErrorAndExit(parent);

              }

          }

         

          private static boolean isJreWithAppContextBug() {

              return badVersionInfo != null;

          }

         

          private static void displayErrorAndExit(Component parent) {

              JLabel msgLabel = new JLabel("<html>" +

                  "Our application cannot run using <b>Web Start</b> with this version of Java.<p><p>" +

                  "Java " + badVersionInfo + " contains a bug acknowledged by Oracle (JDK-8019274).");

              JOptionPane.showMessageDialog(parent, msgLabel, "Java Version Error", JOptionPane.ERROR_MESSAGE);

              System.exit(1);

          }

       

          private static boolean isApplicableJvmType() {

              String vendor = System.getProperty("java.vendor");

              String vmName = System.getProperty("java.vm.name");

              if (vendor != null && vmName != null) {

                  return vmName.contains("Java HotSpot") &&

                         (vendor.equals("Oracle Corporation") ||

                          vendor.equals("Sun Microsystems Inc."));

              }

             

              return false;

          }

       

          private static boolean isWebstart() {

              if (isWebStart == null) {

                  try {

                      basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");            

                      isWebStart = true;

                  }

                  catch (UnavailableServiceException e) {

                      isWebStart = false;

                  }          

                 

                  try {

                      integrationService = (IntegrationService) ServiceManager.lookup("javax.jnlp.IntegrationService");

                  }

                  catch (UnavailableServiceException e) {

                  }

              }

              return isWebStart;

          }

      }