Oliver Gondža
Oliver Gondža

Reputation: 3511

Building modularized Java application targeting both Java 9 and older

My application is working fine with Java 8 and older but fail to load classes that are not part of Java SE and fails with:

class MyClass (in unnamed module @0x4d14b6c2) cannot access class 
sun.tools.attach.HotSpotVirtualMachine (in module jdk.attach) because 
module jdk.attach does not export sun.tools.attach to unnamed module 
@0x4d14b6c2. 

My original idea was to modularize my application and figure out if the classes I need have a public module to declare the dependency properly. However, as soon as I have declared dummy module-info.java, javac started to complain:

modules are not supported in -source 1.6; use -source 9 or higher to enable modules

EDIT: I am instructing maven-compiler-plugin to produce java 6 compatible bytecode as I need the application to support it. The actual arguments used are -g -nowarn -target 1.6 -source 1.6 -encoding UTF-8.

Perhaps I am missing something obvious but how do I build a jar that would work with Jigsaw as well as older java versions without it?

Upvotes: 2

Views: 832

Answers (1)

Oliver Gondža
Oliver Gondža

Reputation: 3511

With help from Jigsaw development mailing list, I managed to get the modularized codebase to build. (I ended up not needing the HotSpotVirtualMachine in particular).

  • Compile module-info.class with -source 9 -target 9 for the app to be runnable on older JVMs as those have no reason to load the class.
  • The rest of the classes should be compiled with appropriate source/target level (Java 9 does not change anything here).

So two javac invocations are needed: by default only classes are compiled and module descriptors are skipped, if compiled using Java 9, module descriptors are compiled skipping all the regular classes.


Maven pom.xml declaration to keep the application buildable and runnable across different JDK versions is a bit clumsy but working:

    <!--
        When using compiler from java 8 and older, ignore module files altogether.
        Otherwise, use 2 phase compilation to build
          - all classes for target version and
          - module-info.java with 9+ source and target level
     -->
    <profiles>
      <profile>
      <id>jigsaw</id>
      <activation>
        <jdk>[1.9,)</jdk>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
              <source>1.9</source>
              <target>1.9</target>
            </configuration>
            <executions>
              <execution>
                <id>module-infos</id>
                <phase>compile</phase>
                <goals>
                  <goal>compile</goal>
                </goals>
                <configuration>
                  <includes>
                    <include>**/module-info.java</include>
                  </includes>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
        <executions>
          <execution>
            <id>default-compile</id>
            <configuration>
              <excludes>
                <exclude>**/module-info.java</exclude>
              </excludes>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Upvotes: 4

Related Questions