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

(logging) LogManager.resetLogger should ignore LinkageError

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_66"
      Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      The LogManager$Cleaner thread will attempt to close all handlers when the JVM is shutdown. This is done by invoking the LogManager.resetLogger method. That method attempts to close each attached handler and ignores any checked or unchecked exception that happens to be thrown from the attached handler. This is done so all remaining handlers are closed even if there is an error encountered.

      When running under GlassFish there are cases where the OSGI bundle used by a handler is shutdown before the cleaner thread is run. In which case calling Handler.close can throw a form of a LinkageError which will prevent any remaining handlers from being closed.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      NoClassDefFoundError can be generated by simply calling Handler.reportError with an exception. By the time the cleaner runs the remapped System.err classloader has been shutdown. This is described in https://java.net/jira/browse/GLASSFISH-21258

      ExceptionInInitializerError can be generated on GF3 when the MailHandler is installed as an OSGI component. In this case, the JavaMail module shutdown and close method fails trying to load the JavaMail classes.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      LinkageError thrown from close should be ignored so all handlers are closed. LinkageError thrown ErrorManager created in System.err should ignored in Handler.reportError.
      ACTUAL -
      The cleaner stops trying to close other handlers.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.NoClassDefFoundError: com/sun/common/util/logging/LoggingOutputStream$StackTraceObjects
      at com.sun.common.util.logging.LoggingOutputStream$LoggingPrintStream.println(LoggingOutputStream.java:231)
      at java.lang.Throwable$WrappedPrintStream.println(Throwable.java:748)
      at java.lang.Throwable.printStackTrace(Throwable.java:655)
      at java.lang.Throwable.printStackTrace(Throwable.java:643)
      at java.lang.Throwable.printStackTrace(Throwable.java:634)
      at java.util.logging.ErrorManager.error(ErrorManager.java:96)
      at java.util.logging.Handler.reportError(Handler.java:241)
      at com.sun.mail.util.logging.MailHandler.reportError(MailHandler.java:1351)
      at com.sun.mail.util.logging.MailHandler.send(MailHandler.java:2358)
      at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:749)
      at java.util.logging.LogManager.resetLogger(LogManager.java:1346)
      at java.util.logging.LogManager.reset(LogManager.java:1332)
      at java.util.logging.LogManager$Cleaner.run(LogManager.java:239)
      Caused by: java.lang.ClassNotFoundException: Unable to load class 'com.sun.common.util.logging.LoggingOutputStream$StackTraceObjects' because the bundle wiring for org.glassfish.main.common.util is no longer valid.
      at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1494)
      at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
      at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

      and

      Exception in thread "Thread-0" java.lang.ExceptionInInitializerError
          at com.sun.mail.util.logging.MailHandler.writeLogRecords0(MailHandler.java:2756)
          at com.sun.mail.util.logging.MailHandler.writeLogRecords(MailHandler.java:2721)
          at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:837)
          at java.util.logging.LogManager.resetLogger(LogManager.java:1192)
          at java.util.logging.LogManager.reset(LogManager.java:1178)
          at java.util.logging.LogManager$Cleaner.run(LogManager.java:256)
      Caused by: java.lang.NullPointerException
          at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
          at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
          at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
          at javax.mail.internet.MimeMessage.<clinit>(MimeMessage.java:1759)
          ... 6 more

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.FileDescriptor;
      import java.io.FileOutputStream;
      import java.io.PrintStream;
      import java.util.Arrays;
      import java.util.logging.Handler;
      import java.util.logging.LogRecord;
      import java.util.logging.Logger;

      public class Closers extends Handler {

          private static final Closers[] closers = new Closers[]{
              new Closers(), new Closers(), new Closers()
          };

          private static final Logger logger = Logger.getLogger("test");
          private static final Logger global = Logger.getGlobal();

          private volatile boolean closed;

          public static void main(String[] args) {
              logger.addHandler(closers[0]);
              logger.addHandler(closers[1]);
              global.addHandler(closers[2]);
          }

          @Override
          public void publish(LogRecord record) {
          }

          @Override
          public void flush() {
          }

          @Override
          public void close() throws SecurityException {
              closed = true;
              PrintStream ps = new PrintStream(new FileOutputStream(FileDescriptor.out));
              ps.println(Arrays.toString(closers));
              //throw new RuntimeException();
              throw new LinkageError();
          }

          @Override
          public String toString() {
              return super.toString() + "{closed=" + closed + '}';
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Patch any custom handlers to to trap LinkageError from Handler.reportError

            dfuchs Daniel Fuchs
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: