Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft version of a modularized twelvemonkeys #685

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Torrenal
Copy link

@Torrenal Torrenal commented Jun 4, 2022

Some key notes here:

  • This creates multi-release jars. I use moditect to do this -- the jars still run on Java 7 and work fine(?) with Java 9+
  • Moditect apparently does not support a build finalName - someone might bring that up with the moditect folks. While there are other ways to create multi-release jars, moditect was the least involved method.
  • Unit tests have not been modularized - they still all pass even if I screw up the module-info files. Modularizing the tests should probably happen. (Heck, I could make it happen, but I'd need to find some time, and there's the question of how to best make it a thing)
  • Properly, the module-info files should be reviewed/edited by the project maintainers, expressly to hide APIs that they don't want being accessed externally. This serves two purposes: It leaves them more free to edit/replace/remove the hidden parts of the project without breaking projects that depend upon this. This can/should be done for security - we don't want anyone combining 3+ unrelated jars into a new mad-gadget RCE exploit.
  • This "Works for me". YMMV. Terms and restrictions may apply. Use at own risk. Do not feed after midnight.

//Torrenal

PS: 'static' is module-info speak for 'optional'

Modularized version of the project.
 - Jar names have changed (sorry!  I blame moditect)
 - Unit tests are not modularized.  This should probably happen...
 - I'm not happy with needing a module-info for projects that have no java source,
    but this is a draft version...  wiser folks than me might be able to find a better
   solution.
 - The module-info files should be considered draft versions.
    Modules provide security, by allowing you to not export packages that don't need
   to be exported, so there's some argument for a project maintainer to sort out
   which packages should be public and which should be private...
Backing out an aborted edit
@haraldk
Copy link
Owner

haraldk commented Jun 4, 2022

Thank you! I'll look into it!

I'm in the process of restructuring the entire library for a version 4. The main things I want to do, is:

  • Get rid of the 3 non-imageio (common) modules for less dependencies
  • Move the necessary parts from those modules into imageio-core (and perhaps rename to imageio-common)
  • Modularize (your suggestions come in very handy here! 😀 )
  • Tweak public/private API in modules
  • Tweak maven modules' coordinate (groupId/artifactId for a better JAR name)

I'm also considering ditching Java 8 support altogether, and require Java 11 from this version, but not fully decided yet.

Anyway: 👍

@Torrenal
Copy link
Author

Torrenal commented Jun 4, 2022

I'd suggest you to keep Java 8 support - if there's any indicator why, look at RHEL which extended their own java 8 support into 2026. For better or worse, Jigsaw(modules) broke backward-compatibility in Java in a big way, we'll be seeing the after-effects of that for years to come.

If you're restructuring things more broadly, we do have more options where modules are concerned.

(I'd feel better about this if there was better direct support for multi-release modules, but meh. We can make our own hammers big enough to make all the bits fit).

True multi-release jars need to be compiled with different target versions of Java. That means multiple compile phases.
Multiple compile phases mean javac gets invoked more than once. Two of the more basic ways to do this are...

  • Use ant to invoke the compiler more times. Reference: https://in.relation.to/2017/02/13/building-multi-release-jars-with-maven/
    I tried this with twelvemonkeys, the javac grumbled at t he first external, non-modularized dependency it saw. I dropped it there and committed to moditect, because I just needed module-info files, not full multi-release support.
  • The franken-jar: (not entirely unlike a shaded jar) This is actually how I modularize 3rd party jars when moditect does not suffice. I create my own maven project that updates the jar to suit my needs, allowing me to add/replace/remove specific class files as necessary
  1. Create your java8 project/jar with all the bells/whistles that you can reasonably fit into java 8. Keep it java-8.

  2. Create a new maven project. Unpack your java-8 jar into your target folder (maven dependency plugin), for inclusion in the jar you're about to make.

  3. Compile the necessary java9+ bits into class files (this is stock maven behavior)

  4. Package the jar - be sure to put the java9+ compiled classes in /META-INF/versions as a proper multi-release jar so that java8 doesn't get exposed to them. Also make sure the manifest has it's Multi-Release: true

    This is actually rather tame as franken-jar's go (I've had to do much much worse things to jars -- thank you gradle).
    I haven't actually done unit-tests specific for java modules, but this looks like you can test the java-8 stuff when you make the java-8 only jar, and repeat the tests against your mutli-release jar when creating it.

@bernhardf-ro
Copy link
Contributor

I have to add a vote for keeping Java 8 support.

Also on the topic of restructuring I would like to add a request:
It would be great if the SPI metadata would be separate from the actual classes, so the libraries can be used without automatic global changes happening to the JVM instance.

@haraldk
Copy link
Owner

haraldk commented Jun 8, 2022

@bernhardf-ro

It would be great if the SPI metadata would be separate from the actual classes, so the libraries can be used without automatic global changes happening to the JVM instance.

Just to make sure I understand this wish... You would like to have the SPI config in META-INF/services/... separate from the normal JAR, to avoid automatic detection?

I think if we do this, we'll need to build two customized JARs for each plugin (one as we do now with everything, and one without the SPI config), as it would otherwise require "normal" usage to depend on twice as many JARs...

Can you file a separate issue for this, and describe the use case, so we can discuss this separately?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants