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

Dependencies of automatic modules are not propagated through module layers

    Details

      Description

      A DESCRIPTION OF THE PROBLEM :
      Hello everyone,

      Consider the following setup:

      We have a system that starts up with one Loader module, which requires several system modules and some non-modular libraries (e.g., libraryX), which are resolved as automatic modules. LibraryX returns a type of libraryY in one of its public methods; however, the Loader module does not explicitly require libraryY. Since the Loader module resolves and ends up reading all automatic modules on the module path (including libraryY), if at least one automatic module is listed in the module descriptor as a requirement, this is not an issue.

      The behavior is implemented in the method makeGraph of the java.lang.module.Resolver class: If the automatic module is resolved, it requires transitive all other automatic modules in the current and parent configurations. Therefore, the Loader module can work with the types of libraryY, even if it only explicitly requires libraryX.

      The Loader is set up to instantiate several plugins as modules, each in their own ModuleLayer. Let's say that pluginA requires the Loader module but also libraryX (but not explicitly libraryY). The Loader module's configuration has already resolved LibraryX as an automatic module. However, after the resolution is complete, pluginA ends up reading only the explicitly required automatic module libraryX from its parent layer, NOT libraryY nor any other automatic module from its parent layer.

      We would have expected the Resolver to check if one of the requirements is an automatic module and therefore add all automatic modules in the same and all parent layers into its readability graph. The current implementation has led to IllegalAccessErrors at runtime when a type of libraryY is returned to pluginA by libraryX:

      java.lang.IllegalAccessError: class com.pluginA.PluginAStarter (in module com.pluginA) cannot access class org.libraryY.MainClass (in module org.libraryY) because module com.pluginA does not read module org.libraryY.

      The explanation can be found in the resolution process of pluginA: LibraryX is not enumerated again, since it is found in the parent layer. The parent configuration's transitive dependencies are evaluated during the creation of the readability graph for pluginA's module layer. However, since automatic modules do not report any transitive requirements, they are not considered. Therefore, libraryY is not added to pluginA's readability graph.

      Is this the intended behavior? And if so, doesn't it violate the principle of reliable configuration? The compiler is unable to find this error since it doesn't know in which layers the modules will be loaded.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Setup a system where moduleA creates a module layer for moduleB. ModuleB requires an automatic moduleC, which return a type residing in libraryA (which is on the module path). Trying to access libraryA from moduleA succeeds, while accessing libraryA from moduleB fails.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      moduleA and moduleB can both access types in libraryA.
      ACTUAL -
      java.lang.IllegalAccessError

      CUSTOMER SUBMITTED WORKAROUND :
      A possible workaround would be to analyze each automatic library's dependencies before deployment, to make sure no Errors are thrown at runtime.

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                alanb Alan Bateman
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: