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

jdeps ignores multi-release when generate-module-info used on command line

XMLWordPrintable

    • b32
    • x86_64
    • generic

        ADDITIONAL SYSTEM INFORMATION :
        $ java -version
        java version "12.0.2" 2019-07-16
        Java(TM) SE Runtime Environment (build 12.0.2+10)
        Java HotSpot(TM) 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)


        A DESCRIPTION OF THE PROBLEM :
        Goal (task at hand) is to convert existing automatic modules to named modules in order to produce (i.e. jlink) an executable. Automatic modules not allowed because they retain the CLASSPATH being shed by move to modules.

        Have successfully converted jars that were not multi-version.

        Unable to generate module-info.java for multi-version jar from Apache (log4j-core-2.11.0.jar) .
        jdeps --generate-module-info . --multi-release 9 ../mods/org.apache.log4j.core.jar
        Error: org.apache.log4j.core.jar is a multi-release jar file but --multi-release option is not set

        Related issue… discussed in a stack overflow article. Note: JDK 12 did not fix it!
        https://stackoverflow.com/questions/53581799/jdeps-command-use-with-multi-release-option-failed
        The one Answer provided suggests this is/was a known defect fixed in JDK12 EA. Six months have gone by and we are on 12.0.2 release at the time this defect was submitted.
        JDK 12 did not fix it!


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        If you already have a project containing a version of log4j-core-2.11.0.jar use it. Next couple of steps will put one into your repository…

        This defect has a simple hello world project attached. Extract contents of zip file into folder and ‘cd’ into folder.

        # Build it
        $ mvn clean install

        # Build created a distribution assembly. Unzip the distribution assembly.
        $ cd target
        $ unzip SurefireStartupIssue-dist.zip
        Archive: SurefireStartupIssue-dist.zip
           creating: SurefireStartupIssue/
           creating: SurefireStartupIssue/conf/
           creating: SurefireStartupIssue/lib/
          inflating: SurefireStartupIssue/conf/log4j2.xml
          inflating: SurefireStartupIssue/lib/spring-beans-5.1.2.RELEASE.jar
          inflating: SurefireStartupIssue/lib/log4j-api-2.11.0.jar
          inflating: SurefireStartupIssue/lib/SurefireStartupIssue-1.0-SNAPSHOT.jar
          inflating: SurefireStartupIssue/lib/log4j-core-2.11.0.jar
          inflating: SurefireStartupIssue/lib/commons-lang3-3.7.jar
          inflating: SurefireStartupIssue/lib/spring-core-5.1.2.RELEASE.jar
          inflating: SurefireStartupIssue/lib/spring-context-5.1.2.RELEASE.jar
          inflating: SurefireStartupIssue/lib/spring-aop-5.1.2.RELEASE.jar
          inflating: SurefireStartupIssue/lib/spring-jcl-5.1.2.RELEASE.jar
          inflating: SurefireStartupIssue/lib/spring-expression-5.1.2.RELEASE.jar

        # Check to see the one provided is an “automatic” module.
        # Remember that jlink doesn’t use/want automatic modules.
        # Hooks them into CLASSPATH… the very thing they are trying to escape.

        $ cd SurefireStartupIssue/
        $ jar --describe-module -f ../lib/log4j-core-2.11.0.jar
        No module descriptor found. Derived automatic module.

        org.apache.logging.log4j.core@2.11.0 automatic
        requires java.base mandated
        provides javax.annotation.processing.Processor with org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor
        provides org.apache.logging.log4j.message.ThreadDumpMessage$ThreadInfoFactory with org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory
        provides org.apache.logging.log4j.spi.Provider with org.apache.logging.log4j.core.impl.Log4jProvider
        contains org.apache.logging.log4j.core
        contains org.apache.logging.log4j.core.appender
        contains org.apache.logging.log4j.core.appender.db
        contains org.apache.logging.log4j.core.appender.db.jdbc
        contains org.apache.logging.log4j.core.appender.mom
        contains org.apache.logging.log4j.core.appender.mom.jeromq
        contains org.apache.logging.log4j.core.appender.mom.kafka
        contains org.apache.logging.log4j.core.appender.nosql
        contains org.apache.logging.log4j.core.appender.rewrite
        contains org.apache.logging.log4j.core.appender.rolling
        contains org.apache.logging.log4j.core.appender.rolling.action
        contains org.apache.logging.log4j.core.appender.routing
        contains org.apache.logging.log4j.core.async
        contains org.apache.logging.log4j.core.config
        contains org.apache.logging.log4j.core.config.builder.api
        contains org.apache.logging.log4j.core.config.builder.impl
        contains org.apache.logging.log4j.core.config.composite
        contains org.apache.logging.log4j.core.config.json
        contains org.apache.logging.log4j.core.config.plugins
        contains org.apache.logging.log4j.core.config.plugins.convert
        contains org.apache.logging.log4j.core.config.plugins.processor
        contains org.apache.logging.log4j.core.config.plugins.util
        contains org.apache.logging.log4j.core.config.plugins.validation
        contains org.apache.logging.log4j.core.config.plugins.validation.constraints
        contains org.apache.logging.log4j.core.config.plugins.validation.validators
        contains org.apache.logging.log4j.core.config.plugins.visitors
        contains org.apache.logging.log4j.core.config.properties
        contains org.apache.logging.log4j.core.config.status
        contains org.apache.logging.log4j.core.config.xml
        contains org.apache.logging.log4j.core.config.yaml
        contains org.apache.logging.log4j.core.filter
        contains org.apache.logging.log4j.core.impl
        contains org.apache.logging.log4j.core.jackson
        contains org.apache.logging.log4j.core.jmx
        contains org.apache.logging.log4j.core.layout
        contains org.apache.logging.log4j.core.lookup
        contains org.apache.logging.log4j.core.message
        contains org.apache.logging.log4j.core.net
        contains org.apache.logging.log4j.core.net.ssl
        contains org.apache.logging.log4j.core.osgi
        contains org.apache.logging.log4j.core.parser
        contains org.apache.logging.log4j.core.pattern
        contains org.apache.logging.log4j.core.script
        contains org.apache.logging.log4j.core.selector
        contains org.apache.logging.log4j.core.time
        contains org.apache.logging.log4j.core.time.internal
        contains org.apache.logging.log4j.core.tools
        contains org.apache.logging.log4j.core.tools.picocli
        contains org.apache.logging.log4j.core.util
        contains org.apache.logging.log4j.core.util.datetime

        # Automatic module looks alright. Let’s convert this to a named module.
        $ mkdir mods
        $ cp lib/log4j-core-2.11.0.jar mods/org.apache.log4j.core.jar
        $ mkdir work; cd work
        $ jar xf ../mods/org.apache.log4j.core.jar



        # Bug demonstrated when command ignores multi-release option when generate-module-info used.
        $ jdeps --generate-module-info . ../mods/org.apache.log4j.core.jar
        Error: org.apache.log4j.core.jar is a multi-release jar file but --multi-release option is not set

        $ jdeps --generate-module-info . --multi-release 9 ../mods/org.apache.log4j.core.jar
        Error: org.apache.log4j.core.jar is a multi-release jar file but --multi-release option is not set

        $ jdeps --multi-release 9 ../mods/org.apache.log4j.core.jar # Notice how this does work!
        org.apache.log4j.core.jar -> java.base
        org.apache.log4j.core.jar -> java.compiler
        <output truncated for brevity – dependencies listed >


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expected generation of a module-info.java file.
        ACTUAL -
        Error message printed. No module-info.java file produced.

        ---------- BEGIN SOURCE ----------
        2 files listed: Main.java and a pom.xml

        $ cat src/main/java/com/samplebiz/surefirestartupissue/Main.java
        package com.samplebiz.surefirestartupissue;

        import org.apache.logging.log4j.LogManager;
        import org.apache.logging.log4j.Logger;

        public class Main {
            protected static Logger logger = LogManager.getLogger(Main.class);

            /**
             * @param args the command line arguments
             */
            public static void main(String[] args) {
                logger.info(Main.class.getSimpleName() + " starting");
                System.out.println("Hello world!");
                logger.info(Main.class.getSimpleName() + " finished");
            }
        }

        -------------------

        pom.xml

        $ cat pom.xml
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <groupId>com.samplebiz</groupId>
            <artifactId>SurefireStartupIssue</artifactId>
            <version>1.0-SNAPSHOT</version>
            <packaging>jar</packaging>
            <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <jdk.version>11</jdk.version>
                <maven.compiler.source>12</maven.compiler.source>
                <maven.compiler.target>12</maven.compiler.target>
                <javadoc.opts>-Xdoclint:none</javadoc.opts>

                <!-- define jdk versions -->
                <maven.compiler.source>${jdk.version}</maven.compiler.source>
                <maven.compiler.target>${jdk.version}</maven.compiler.target>

                <!-- define versions -->
                <log4j.version>2.11.0</log4j.version>
                <junit.version>4.12</junit.version>
                <powermock.version>2.0.0</powermock.version>
                <easymock.version>3.6</easymock.version>
                <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
                <maven-source-plugin.version>3.1.0</maven-source-plugin.version>
                <maven-deploy-plugin.version>3.0.0-M1</maven-deploy-plugin.version>
                <commons-lang3.version>3.7</commons-lang3.version>
                <javadoc.version>3.0.0</javadoc.version>
                <maven-assembly-plugin.version>3.1.0</maven-assembly-plugin.version>
                <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
                <maven-surefire-plugin.version>3.0.0-M3</maven-surefire-plugin.version>
                <mockito-core.version>2.18.3</mockito-core.version>
                <jacoco-maven-plugin.version>0.8.4</jacoco-maven-plugin.version>
                <versions-plugin.version>2.7</versions-plugin.version>
                <org.springframework.version>5.1.2.RELEASE</org.springframework.version>

                <!-- argLine -->
                <argLine> </argLine>
            </properties>

            <!-- dependencies on external jars -->
            <dependencies>
                <dependency>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-api</artifactId>
                    <version>${log4j.version}</version>
                </dependency>

                <dependency>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-core</artifactId>
                    <version>${log4j.version}</version>
                </dependency>

                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                    <scope>test</scope>
                </dependency>

                <dependency>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                    <version>${commons-lang3.version}</version>
                </dependency>

                <!-- Added to mvnrepository repositories in ~/.m2/settings.xml -->
                <!-- https://mvnrepository.com/artifact/org.easymock/easymock -->
                <dependency>
                    <groupId>org.easymock</groupId>
                    <artifactId>easymock</artifactId>
                    <version>${easymock.version}</version>
                    <scope>test</scope>
                </dependency>

                <!-- Added to mvnrepository repositories in ~/.m2/settings.xml -->
                <!-- https://mvnrepository.com/artifact/org.powermock/powermock-api-easymock -->
                <dependency>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-core</artifactId>
                    <version>${powermock.version}</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-api-easymock</artifactId>
                    <version>${powermock.version}</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-module-junit4</artifactId>
                    <version>${powermock.version}</version>
                    <scope>test</scope>
                </dependency>

        <!--
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${org.springframework.version}</version>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${org.springframework.version}</version>
                </dependency>
        -->

            </dependencies>

            <build>
                <finalName>${project.artifactId}</finalName>
                <plugins>

                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>versions-maven-plugin</artifactId>
                        <version>${versions-plugin.version}</version>
                        <configuration>
                            <generateBackupPoms>false</generateBackupPoms>
                        </configuration>
                    </plugin>

                    <!-- Set a JDK compiler level -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>${maven-compiler-plugin.version}</version>
                        <configuration>
                            <source>${jdk.version}</source>
                            <target>${jdk.version}</target>
                            <release>${jdk.version}</release>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-source-plugin</artifactId>
                        <version>${maven-source-plugin.version}</version>
                        <configuration>
                            <skipSource>true</skipSource>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-deploy-plugin</artifactId>
                        <version>${maven-deploy-plugin.version}</version>
                        <configuration>
                            <skip>true</skip>
                        </configuration>
                    </plugin>

                    <!-- Surefire plugin required to specify version and set
                    to use single process => forkCount = 1 -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>${maven-surefire-plugin.version}</version>
                        <configuration>
                            <reuseForks>false</reuseForks>
                            <forkCount>1</forkCount>
                            <argLine>@{argLine} -Dfile.encoding=UTF-8</argLine>
                            <skipTests>true</skipTests>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                        <version>${jacoco-maven-plugin.version}</version>
                        <executions>

                            <!-- Prepares the property pointing to the JaCoCo runtime agent which
                                is passed as VM argument when Maven's Surefire plugin is executed.
                            -->
                            <execution>
                                <id>pre-unit-test</id>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                                <configuration>
                                    <destFile>${project.build.directory}/coverage-reports/jacoco-unit-test.exec</destFile>
                                </configuration>
                            </execution>

                            <!-- Ensures that the code coverage report for unit tests is created after
                                 unit tests have been run.
                            -->
                            <execution>
                                <id>post-unit-test</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>report</goal>
                                </goals>
                                <configuration>
                                    <!-- Sets the path to the file which contains the execution data. -->
                                    <dataFile>${project.build.directory}/coverage-reports/jacoco-unit-test.exec</dataFile>
                                    <!-- Sets the output directory for the code coverage report. -->
                                    <outputDirectory>${project.build.directory}/coverage-reports</outputDirectory>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Javadoc of each class -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <version>${javadoc.version}</version>
                        <configuration>
                            <doctitle>API for ${project.name} ${project.version}</doctitle>
                            <show>private</show>
                            <source>${jdk.version}</source>
                            <docfilessubdirs>true</docfilessubdirs>
                        </configuration>
                        <executions>
                            <execution>
                                <id>attach-javadocs</id>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>copy-dependencies</id>
                                <phase>prepare-package</phase>
                                <goals>
                                    <goal>copy-dependencies</goal>
                                </goals>
                                <configuration>
                                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                                    <overWriteReleases>false</overWriteReleases>
                                    <overWriteSnapshots>false</overWriteSnapshots>
                                    <overWriteIfNewer>true</overWriteIfNewer>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Make this jar executable complete with manifest -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-jar-plugin</artifactId>
                        <version>${maven-jar-plugin.version}</version>
                        <configuration>
                            <!-- DO NOT include log4j.properties file in your Jar -->
                            <excludes>
                                <exclude>*.properties</exclude>
        <!-- <exclude>**/log4j.properties</exclude>
                                <exclude>**/mandelbrot.properties</exclude>-->
                            </excludes>
                            <archive>
                                <manifest>
                                    <!-- Jar file main entry point -->
                                    <mainClass>com.wilasch.mandelbrot.navigator.Main</mainClass>
                                    <classpathPrefix>./lib/</classpathPrefix>
                                    <addClasspath>true</addClasspath>
                                </manifest>

                                <!--External resources will be placed under conf/-->
                                <manifestEntries>
                                    <Class-Path>./conf/</Class-Path>
                                </manifestEntries>
                            </archive>
                        </configuration>
                    </plugin>

                    <plugin>
                        <artifactId>maven-assembly-plugin</artifactId>
                        <version>${maven-assembly-plugin.version}</version>
                        <configuration>
                            <descriptors>
                                <descriptor>${basedir}/src/assembly/distribution-zip.xml</descriptor>
                            </descriptors>
                        </configuration>
                        <executions>
                            <execution>
                                <phase>package</phase>
                                <goals>
                                    <goal>single</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                </plugins>
            </build>
        </project>



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

        CUSTOMER SUBMITTED WORKAROUND :
        No workaround known.

        FREQUENCY : always


              mchung Mandy Chung
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: