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

Regression: NPE during reparse when using persistent code cache and optimistic types

    XMLWordPrintable

Details

    • b153
    • generic
    • generic

    Description

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

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.10586]

      A DESCRIPTION OF THE PROBLEM :
      When optimistic types and persistent code caching are enabled an NPE may be thrown when type specialization results in a reparse of the function source on any but the first run / JVM execution.

      If and when a NPE is triggered appears to depend on the specific content / complexity of the script and how it is loaded.

      REGRESSION. Last worked in version 8u77

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.8.0_102"
      Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

      previous:
      java version "1.8.0_71"
      Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
      Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) create two script files "classpath.js" and "classpath-test.js" (see "source code for executable test case" - test scripts with more abstraction failed to reproduce issue reliably enough)

      2) start the jjs shell via: jjs -pcc=true -ot=true -doe=true
      3) load classpath-test.js via JS statement: load('./classpath-test.js');
      4) load classpath.js via JS statement: load('./classpath.js');
      5) exit the jjs shell via: exit();

      6) repeat steps 2 through 5 at least three times (it always requires three runs on my machine to reproduce the issue)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      All repetitions of steps 2 through 5 produce the exact same output:

      output of 3)
      function (name, deps, factory){
              // simply call factory with the expected Java object
              factory(Java);
      }

      output of 4)
      java.lang.RuntimeException: java.lang.ClassNotFoundException: de.axelfaust.alfresco.nashorn.repo.loaders.AlfrescoClasspathURLStreamHandler
      java.lang.RuntimeException: java.lang.ClassNotFoundException: de.axelfaust.alfresco.nashorn.repo.loaders.AlfrescoClasspathURLStreamHandler
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:397)
       [... stack frames ommitted for readability ...]
              at jdk.nashorn.tools.Shell.main(Shell.java:111)
      Caused by: java.lang.ClassNotFoundException: de.axelfaust.alfresco.nashorn.repo.loaders.AlfrescoClasspathURLStreamHandler
              at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
       [... stack frames ommitted for readability ...]
              at jdk.nashorn.internal.scripts.Script$Recompilation$7$846$classpath.classpath_loader_root$classpath_loader$streamHandler(./classpath.js:24)
              at jdk.nashorn.internal.scripts.Script$Recompilation$16$541A$classpath$cu1$restOf.classpath_loader_root$classpath_loader(./classpath.js:20)
              at jdk.nashorn.internal.scripts.Script$Recompilation$11$287AAA$classpath_test.define(./classpath-test.js:15)
              at jdk.nashorn.internal.scripts.Script$Recompilation$10$138$classpath.classpath_loader_root(./classpath.js:12)
              at jdk.nashorn.internal.scripts.Script$Recompilation$9$103$classpath.:program(./classpath.js:4)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
              at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
              ... 13 more

      This exception is EXPECTED as we have not included the custom Java class on the classpath.
      ACTUAL -
      the output of 4) changes on a repitition of steps 2 through 5 (in my environment it reliably occurs on the 3rd repetition)

      java.lang.NullPointerException
      jdk.nashorn.internal.runtime.ParserException: java.lang.NullPointerException
              at jdk.nashorn.internal.runtime.Context$ThrowErrorManager.error(Context.java:434)
              at jdk.nashorn.internal.parser.Parser.handleParseException(Parser.java:386)
              at jdk.nashorn.internal.parser.Parser.parse(Parser.java:285)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.reparse(RecompilableScriptFunctionData.java:405)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.compileTypeSpecialization(RecompilableScriptFunctionData.java:723)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.getBest(RecompilableScriptFunctionData.java:905)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.getBest(ScriptFunctionData.java:375)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.getReturnType(RecompilableScriptFunctionData.java:893)
              at jdk.nashorn.internal.codegen.TypeEvaluator.getEvaluatedType(TypeEvaluator.java:236)
              at jdk.nashorn.internal.codegen.TypeEvaluator.getOptimisticType(TypeEvaluator.java:95)
              at jdk.nashorn.internal.codegen.Compiler.getOptimisticType(Compiler.java:576)
              at jdk.nashorn.internal.codegen.OptimisticTypesCalculator.leaveOptimistic(OptimisticTypesCalculator.java:234)
              at jdk.nashorn.internal.codegen.OptimisticTypesCalculator.leaveDefault(OptimisticTypesCalculator.java:200)
              at jdk.nashorn.internal.ir.visitor.NodeVisitor.leaveCallNode(NodeVisitor.java:233)
       [... stack frames ommitted for readability ...]
              at jdk.nashorn.internal.codegen.CompilationPhase.transformFunction(CompilationPhase.java:628)
              at jdk.nashorn.internal.codegen.CompilationPhase.access$100(CompilationPhase.java:55)
              at jdk.nashorn.internal.codegen.CompilationPhase$OptimisticTypeAssignmentPhase.transform(CompilationPhase.java:255)
              at jdk.nashorn.internal.codegen.CompilationPhase.apply(CompilationPhase.java:624)
              at jdk.nashorn.internal.codegen.Compiler.compile(Compiler.java:655)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.compileTypeSpecialization(RecompilableScriptFunctionData.java:725)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.getBest(RecompilableScriptFunctionData.java:905)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.getBest(ScriptFunctionData.java:375)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.getBestInvoker(ScriptFunctionData.java:237)
              at jdk.nashorn.internal.runtime.ScriptFunction.findCallMethod(ScriptFunction.java:871)
              at jdk.nashorn.internal.runtime.ScriptObject.lookup(ScriptObject.java:1825)
              at jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:104)
              at jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:98)
              at jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker.getGuardedInvocation(CompositeTypeBasedGuardingDynamicLinker.java:176)
              at jdk.internal.dynalink.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124)
              at jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:154)
              at jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:253)
              at jdk.nashorn.internal.scripts.Script$Recompilation$9$287AAA$classpath_test.define(./classpath-test.js:15)
              at jdk.nashorn.internal.scripts.Script$Recompilation$8$138$classpath.classpath_loader_root(./classpath.js:12)
              at jdk.nashorn.internal.scripts.Script$Recompilation$7$103$classpath.:program(./classpath.js:4)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
              at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
              at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1224)
              at jdk.nashorn.internal.runtime.Context.load(Context.java:837)
              at jdk.nashorn.internal.objects.Global.load(Global.java:1530)
              at jdk.nashorn.internal.scripts.Script$Recompilation$5$\^shell\_.:program(<shell>:1)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
              at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
              at jdk.nashorn.internal.runtime.Context.eval(Context.java:736)
              at jdk.nashorn.internal.runtime.Context.eval(Context.java:671)
              at jdk.nashorn.tools.Shell.readEvalPrint(Shell.java:438)
              at jdk.nashorn.tools.Shell.run(Shell.java:160)
              at jdk.nashorn.tools.Shell.main(Shell.java:135)
              at jdk.nashorn.tools.Shell.main(Shell.java:111)
      java.lang.NullPointerException
      java.lang.NullPointerException
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.compileTypeSpecialization(RecompilableScriptFunctionData.java:728)
              at jdk.nashorn.internal.runtime.RecompilableScriptFunctionData.getBest(RecompilableScriptFunctionData.java:905)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.getBest(ScriptFunctionData.java:375)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.getBestInvoker(ScriptFunctionData.java:237)
              at jdk.nashorn.internal.runtime.ScriptFunction.findCallMethod(ScriptFunction.java:871)
              at jdk.nashorn.internal.runtime.ScriptObject.lookup(ScriptObject.java:1825)
              at jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:104)
              at jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:98)
              at jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker.getGuardedInvocation(CompositeTypeBasedGuardingDynamicLinker.java:176)
              at jdk.internal.dynalink.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124)
              at jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:154)
              at jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:253)
              at jdk.nashorn.internal.scripts.Script$Recompilation$9$287AAA$classpath_test.define(./classpath-test.js:15)
              at jdk.nashorn.internal.scripts.Script$Recompilation$8$138$classpath.classpath_loader_root(./classpath.js:12)
              at jdk.nashorn.internal.scripts.Script$Recompilation$7$103$classpath.:program(./classpath.js:4)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
              at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
              at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1224)
              at jdk.nashorn.internal.runtime.Context.load(Context.java:837)
              at jdk.nashorn.internal.objects.Global.load(Global.java:1530)
              at jdk.nashorn.internal.scripts.Script$Recompilation$5$\^shell\_.:program(<shell>:1)
              at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
              at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
              at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
              at jdk.nashorn.internal.runtime.Context.eval(Context.java:736)
              at jdk.nashorn.internal.runtime.Context.eval(Context.java:671)
              at jdk.nashorn.tools.Shell.readEvalPrint(Shell.java:438)
              at jdk.nashorn.tools.Shell.run(Shell.java:160)
              at jdk.nashorn.tools.Shell.main(Shell.java:135)
              at jdk.nashorn.tools.Shell.main(Shell.java:111)

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      === Source of classpath-test.js
      // these need to be globally defined
      var applicationContext, getSimpleLogger, define;

      applicationContext = null;
      getSimpleLogger = function() {
      return Object.create(Object.prototype, {
      traceEnabled : {
      value : false
      }
      });
      };

      define = function (name, deps, factory){
      // simply call factory with the expected Java object
      factory(Java);
      };

      === Source of classpath.js (https://github.com/AFaust/alfresco-nashorn-script-engine/blob/cadf69c2e3fb91fa58c57b8b92dab6e435ca5c67/repository/src/main/resources/de/axelfaust/alfresco/nashorn/repo/loaders/classpath.js)
      /* globals -require */
      /* globals getSimpleLogger: false */
      /* globals applicationContext: false */
      (function classpath_loader_root()
      {
          'use strict';
          // applicationContext only set during engine setup
          var streamHandler = applicationContext ? applicationContext.getBean('de.axelfaust.alfresco.nashorn.repo-classpathURLStreamHandler')
                  : null;

          // non-extensible raw classpath loader (scripts located anywhere in classpath)
          define('classpath', [ 'nashorn!Java' ], function classpath_loader(Java)
          {
              var URL, logger, loader;

              logger = getSimpleLogger('de.axelfaust.alfresco.nashorn.repo.processor.NashornScriptProcessor.loader.classpath');
              URL = Java.type('java.net.URL');
              if (streamHandler === null)
              {
                  streamHandler = (function()
                  {
                      var AlfrescoClasspathURLStreamHandler;

                      AlfrescoClasspathURLStreamHandler = Java
                              .type('de.axelfaust.alfresco.nashorn.repo.loaders.AlfrescoClasspathURLStreamHandler');
                      streamHandler = new AlfrescoClasspathURLStreamHandler();
                      streamHandler.basePath = 'alfresco';
                      streamHandler.extensionPath = 'extension';

                      return streamHandler;
                  }());
              }

              /**
               * This loader module provides the capability to load classpath-stored scripts as AMD modules.
               *
               * @exports classpath
               * @author Axel Faust
               */
              loader = {
                  /**
                   * Loads a script stored on the classpath from normalized module ID.
                   *
                   * @instance
                   * @param {string}
                   * normalizedId - the normalized ID of the module to load
                   * @param {function}
                   * require - the context-sensitive require function
                   * @param {function}
                   * load - the callback to load either a pre-built object as the module result or a script defining a module from a
                   * script URL
                   */
                  load : function classpath_loader__load(normalizedId, require, load)
                  {
                      var url = new URL('rawclasspath', null, -1, normalizedId, streamHandler);

                      if (logger.traceEnabled)
                      {
                          logger.trace('Loading module id {} from classpath', normalizedId);
                      }

                      load(url, true);
                  }
              };

              Object.freeze(loader.load);
              Object.freeze(loader);

              return loader;
          });

          // extensible alfresco classpath loader (scripts located in /alfresco/extension/ or /alfresco/)
          define('extensible-classpath', [ 'nashorn!Java' ], function extensible_classpath_loader__load(Java)
          {
              var URL, logger, loader;

              logger = getSimpleLogger('de.axelfaust.alfresco.nashorn.repo.processor.NashornScriptProcessor.loader.extensible-classpath');
              URL = Java.type('java.net.URL');
              if (streamHandler === null)
              {
                  streamHandler = (function()
                  {
                      var AlfrescoClasspathURLStreamHandler;

                      AlfrescoClasspathURLStreamHandler = Java
                              .type('de.axelfaust.alfresco.nashorn.repo.loaders.AlfrescoClasspathURLStreamHandler');
                      streamHandler = new AlfrescoClasspathURLStreamHandler();
                      streamHandler.basePath = 'alfresco';
                      streamHandler.extensionPath = 'extension';

                      return streamHandler;
                  }());
              }

              /**
               * This loader module provides the capability to load "extensible classpath"-stored scripts as AMD modules in such a way that
               * scripts in the /alfresco/extension/ override scripts in /alfresco/.
               *
               * @exports extensible-classpath
               * @author Axel Faust
               */
              loader = {
                  /**
                   * Loads a script stored on the "extensible classpath" from normalized module ID.
                   *
                   * @instance
                   * @param {string}
                   * normalizedId - the normalized ID of the module to load
                   * @param {function}
                   * require - the context-sensitive require function
                   * @param {function}
                   * load - the callback to load either a pre-built object as the module result or a script defining a module from a
                   * script URL
                   */
                  load : function extensible_classpath_loader__load(normalizedId, require, load)
                  {
                      var url = new URL('extclasspath', null, -1, normalizedId, streamHandler);

                      if (logger.traceEnabled)
                      {
                          logger.trace('Loading module id {} from extensible classpath', normalizedId);
                      }

                      load(url, true);
                  }
              };

              Object.freeze(loader.load);
              Object.freeze(loader);

              return loader;
          });
      }());

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

      CUSTOMER SUBMITTED WORKAROUND :
      Disabling either persistent code cache or optimistic types has in all tests shown to reliably work around this issue.

      Attachments

        Activity

          People

            hannesw Hannes Wallnoefer
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: