Using legacy jar files with jlink

Thomas Brand tom at trellis.ch
Fri Nov 17 00:21:59 UTC 2017


Thanks for the quick answer!

On Fri, November 17, 2017 00:35, mark.reinhold at oracle.com wrote:
> 2017/11/16 15:03:37 -0800, Thomas Brand <tom at trellis.ch>:
>
>> this is my first post here, I hope this is the right place to ask a
>> question about how to use jlink.
>
> Yes, it is!
>
>
>> For a given scenario with modules a and b, a using methods of b,
>> following instructions I managed to create a runnable image that can be
>> called (from inside exploded image) like
>>
>> $ ./bin/java a.A
>> A.main() called
>> B() called
>> string from B:test()
>>
>> this works nicely, also both modules are shown with $ ./bin/java
>> --list-modules
>> abjava.base at 10-internal
>>
>> My question is if it's possible to create that image if module b would
>> be a legacy jar with just the .class files in it.
>
> No.  There's no place in the image to store arbitrary JAR files, and
> even if there were there'd be no way to guarantee that all the other JAR
> files required by those JAR files are present, since they're just JAR
> files rather than modules.  An image built by jlink is intended to be
> complete, consistent, and runnable as-is rather than something that might
> need additional JAR files just in order to launch.
>
>> I understand it's possible
>> to auto-generate the module-info.java for this legacy b.jar.
>>
>> I was thinking to be smart and just compile the generated
>> module-info.java for b.jar and then put it to the legacy b.jar or put
>> the module-info.class to the classpath in order to make it modular and
>> then use for the jlink step. However that doesn't work:
>>
>>
>> $JAVAC -d compile_out src/modb/module-info.java
>> src/modb/module-info.java:2: error: package is empty or does not exist:
>> b exports b; ^
>> 1 error
>>
>
> To make this work, copy the content of b.jar into compile_out before you
> run javac so that the compiler can detect that the package is not empty.
>

That was the issue, it works now. I also tried using -cp to point to the
legacy jar but obviously it's different when putting the contents to
compile_out.

>> How can a legacy jar file without access to source files be used as a
>> module, is it possible at all? The idea is to use legacy jar files in
>> conjunction with jlink to be used in self-contained runtime images.
>
> It's possible, as above, but it can fail in many ways.  If the legacy
> JAR files contain conflicting packages then the module system won't be
> able to load them.  Your generated module-info.java files could have
> missing dependences, especially if any of the legacy code uses reflection.
>

Good to know to keep an eye on that.

>
> It's really best to modularize an existing component properly, at the
> source.  If you can't do that, for whatever reason, then it's generally
> safer to leave legacy JAR files on the class path.  You can still use
> jlink to generate a custom image containing just the modules that you
> need; you'll just have to run that image with a non-empty class path.
>

That's another welcome hint to explore. It could well be interesting to
set a system library path for .so files that are packed to the image and
loaded at runtime by modules IIUC.

I read on https://jnbridge.com/blog/legacy-developers-guide-java-9:

-----%<-----
It’s also possible that you might not want to modularize a JAR file, or
that the JAR file belongs to someone else, so you can’t modularize it
yourself. In that case, you can still put the JAR file into the module
path; it becomes an automatic module. An automatic module is considered a
module even though it doesn’t have a module-info.class file.
...
This means that it’s possible to make an unmodularized classpath JAR file
into a module with no work at all: Legacy JAR files become modules
automatically, albeit without some of the information needed to determine
whether all required modules are really there, and to determine what is
missing.
----->%-----

So I tried
$ $JLINK --module-path jar:legacy_jar:$JAVA_HOME/jmods --add-modules a
--output distimage
Error: module-info.class not found for b module

When compiling module-info.java with the extracted b.jar as suggested
above, repacking b.jar with included module-info.class doesn't show an
error:

$ $JLINK --module-path jar:legacy_pimped_jar/:$JAVA_HOME/jmods
--add-modules a --output distimage

And the image works.

Thanks again for your valuable hints. I might come back again later.
Best regards
Thomas


> - Mark
>
>




More information about the jigsaw-dev mailing list