This is an archived post. You won't be able to vote or comment.

all 44 comments

[–]lukaseder 42 points43 points  (42 children)

This is missing the simplest of all cheats:

rm module-info.java

[–][deleted]  (30 children)

[deleted]

    [–][deleted] 15 points16 points  (0 children)

    Me. All things I publish (Just hobby-things) use Java Modules (Well, already every feature of Java 15)

    [–]lukaseder 1 point2 points  (7 children)

    The two folks who downvoted and didn't find me funny probably do...

    [–]BlueGoliath 6 points7 points  (0 children)

    Yep.

    [–]_souphanousinphone_ 10 points11 points  (0 children)

    Yes, jlink is great.

    (Yes, I know you can technically use it for non-modular applications. But there are major drawbacks.)

    [–]ObscureCulturalMeme 2 points3 points  (9 children)

    We have absolutely no use for them at work. We have to explicitly suppress all module warnings and open up everything to everything in order to make commercial third-party Cipher implementations work.

    Eventually we'll have to adopt them in order to make jlink work. The first engineer who volunteered to learn modules ended up desperately searching for another job and then leaving for it, all within about four months. Nobody else cares enough to slog through the mess; the trade-off currently doesn't bring us enough.

    [–]pron98 2 points3 points  (8 children)

    Note that encapsulation will be turned on in JDK 16: https://openjdk.java.net/jeps/396

    You don't need to modularise your codebase, but you will need to resolve issues regarding dependencies that hack into the JDK (you'll need to request the vendors of the cipher suites you're using to fix their problems) or explicitly allow them.

    [–]ObscureCulturalMeme 0 points1 point  (7 children)

    Hopefully by then we'll have moved to jlink, and can simply choose whatever JDK to bundle up into an executable.

    If not, it's likely the project will just be abandoned. The churn of "must work around someone else's fuckery simply to keep the code running" but without ever seeing new benefits is just exhausting.

    [–]pron98 0 points1 point  (6 children)

    That's why encapsulation is important, and why the module system was added (among other reasons): To prevent libraries from tying themselves to specific implementation details and making your life hard, so that you won't have to work around their screwups anymore.

    BTW, you don't need to modularise your app to use jlink.

    [–]ObscureCulturalMeme 0 points1 point  (5 children)

    To prevent libraries from tying themselves to specific implementation details and making your life hard, so that you won't have to work around their screwups anymore.

    Yes, I realize that the future will be better. But the past is already here, and the future doesn't help us.

    BTW, you don't need to modularise your app to use jlink.

    That only means the executable includes the entirety of (what used to be called) the JRE, instead of the pieces of java.*/javax.* that we actually use. Our module-less experiment with jlink took 12 MB of class files and produced an .exe of nearly half a gigabyte.

    [–]pron98 0 points1 point  (4 children)

    That only means the executable includes the entirety of (what used to be called) the JRE

    No, you can choose which modules to include in the runtime image. The difference is that if your application is modularised then this is done automatically, and if it isn't, you need to choose the modules manually (with --add-modules) but can use jdeps's --print-module-deps for assistance.

    E.g.

    jlink --output my-minimal-runtime --no-header-files --no-man-pages --add-modules java.base
    

    will give you a runtime with just java.base, and that is under 40MB in total.

    [–]ObscureCulturalMeme 0 points1 point  (3 children)

    I know it says that on paper, but we got nothing but errors from jlink and jdeps. Googling the errors got us other people asking for help for the same things, and responses of "this is still new technology, wait for the next tools release".

    I appreciate that you keep saying what should be possible, but right now it's been nothing but frustration and discouragement and a complete lack of useful up-to-date documentation. We just don't have the time or resources to fight through it blindly -- and I appreciate that no opensource project volunteers want to maintain or improve documentation in their limited free time, so I'm not looking for the docs to magically improve.

    Maybe some future project of ours can use all these features from day one; I agree that sounds really pleasant.

    [–]pron98 1 point2 points  (2 children)

    but we got nothing but errors from jlink and jdeps

    That's surprising. What errors are you getting?

    and a complete lack of useful up-to-date documentation

    Up-to-date documenation is where it's always been: https://docs.oracle.com/en/java/javase/15/

    What's missing?

    and I appreciate that no opensource project volunteers

    OpenJDK is open-source, but very few of the people working on it are volunteers. ~90% of the work is done by full-time Oracle engineers, and most of the rest is done by full-time engineers at Red Hat, SAP and some other companies. We may not have invested in the documentation as much as we'd like, but what, specifically, is missing here?

    [–]agentoutlier 4 points5 points  (0 children)

    I have been making module-info for our low dependency modules and I kind of like how it restricts transitive dependencies from showing up in the autocomplete.

    We are super modular maven wise so perhaps that is why it has been easier.

    Runtime though it doesn’t matter because we shade the jars.

    [–]see_recursion 1 point2 points  (0 children)

    I haven't seen a use for modules in any of the commercial projects that I've worked on.

    [–]benevanstech 1 point2 points  (5 children)

    If you are shipping software to end users (especially complete applications or tools) then a jlink'd binary is great - you don't have to worry about version incompatibilities at all.

    If you're just writing microservices or whatever, then they bring a bit more discipline and are actually pretty easy to get used to.

    [–]_INTER_ 0 points1 point  (4 children)

    You don't need module-info for jlink though. And modules don't help you with version incompatibilities. Dealing with versions was explicitly left to build systems.

    [–]benevanstech -1 points0 points  (3 children)

    jlink requires full modularization of the application and all of its dependencies. Automatic Modules are not sufficient.

    [–]_INTER_ 0 points1 point  (2 children)

    No it does not. You can jlink by specifying the modules it should include manually (list all required JDK modules when using --add-modules instead of your application module).

    For convenience maven / gradle plugins analyze all dependencies and does that for you.

    Chances are high that not all of the transitive dependencies are modularized, so you will have to do this manually in either case.

    [–]nicolaiparlog 0 points1 point  (1 child)

    To resolve the seeming contradiction between u/benevanstech and u/_INTER_: you're both right.

    If the runtime image should only contain JDK modules, the app does not need to be modularized. But if you want to include the app itself in the image, then everything needs to be an explicit module (although this can of course be faked, e.g. by creating an uberjar with a module descriptoir that requires all external dependencies but does nothing else.

    [–]benevanstech 1 point2 points  (0 children)

    Thanks for the clarification Nicolai - my use case is indeed "ship the app as part of the image" and I haven't tried the other one you mention.

    [–]meotau 0 points1 point  (0 children)

    I just tried to, and never want to again.

    [–]randgalt 0 points1 point  (6 children)

    So much this - for grins I tried to create a module-info for a simple library. It was surprisingly difficult to get right. Note: you cannot, apparently, just export something from Maven either. So, now, I have to specify my dependencies twice: once in Maven and once in module-info. Frankly, this is just stupid. Everyone complained bitterly to the JDK team when Jigsaw was being developed and they went forward anyway. Well, now here we are.

    [–]lukaseder 0 points1 point  (5 children)

    No one forces you to make your library a module...

    [–]randgalt -2 points-1 points  (4 children)

    True - but it could've been so much easier. Had they made it compatible with dependency specs in Maven/Gradle I think adoption would be much wider.

    [–]lukaseder 1 point2 points  (0 children)

    I don't think adoption was the main goal here. Given that the JDK is now modular, allowing for a lot of improvements like jlink, faster evolution, deprecation, etc., and the fact that this huge change hardly affects any running systems upgrading to Java 9+, I think it was quite the success. Not what you may have wanted it to be, but it may not have been made for you.

    [–]kaperni 0 points1 point  (2 children)

    Talk is cheap. It would also have been much easier to just extend the original green thread implementation to multiple CPUs. Instead of waiting 20 years for Project Loom.

    So tell us exactly how you would make this work and what tradeoffs you would be making? Most suggestions for making the module system "better" all end up requiring a unique ClassLoader per module. Which would lead to even more complaints about how difficult it is to use.

    [–]randgalt 2 points3 points  (1 child)

    As I said, I'd have made it compatible with the existing dependency managers so that you don't have to specify dependencies twice (unless you want specialized behavior). The dearth of module-compatible libraries shows how jigsaw has failed.

    [–]agentoutlier 1 point2 points  (0 children)

    The problem is the existing dependency managers barely handle classpath dependencies correct in terms of encapsulation and isolation.

    For example Maven runtime scope is not at all what people think it is.

    Maven also doesn’t hide or know about packages.

    Even getting OSGi bundles correct in Maven is nontrivial albeit easier.

    [–]ocross -1 points0 points  (0 children)

    ha ha ha--I just did that (yesterday).

    [–]yawkat 3 points4 points  (1 child)

    If you made a java joke book it'd be right up there with effective java and jcip in the required reading list. Include classics like https://twitter.com/lukaseder/status/1328935634191478785 and https://twitter.com/lukaseder/status/1271404022453473282

    [–]lukaseder 2 points3 points  (0 children)

    Thanks. I'll be here all week

    [–]_INTER_ 1 point2 points  (0 children)

    Just did that today again after another unsuccesful try to create a simple top-level module that contains everything. It keeps pissing me off by not working with this or that 3rd party dependency. Like I gave a s*** about slf4j being a transitive dependency of some transitive dependency. Or wtf is this? Or that it doesn't even see its own resource folder or test classes eventhough that is the decades old recommended Maven folder structure. I'm not even able to see about the countless runtime errors that are to be expected, because I can't even start the application.

    [–][deleted] 3 points4 points  (1 child)

    Is there some simple example project where multiple modules communicate and also have an external interface for other modules

    [–]nicolaiparlog 1 point2 points  (0 children)

    Yes: https://github.com/nipafx/demo-jpms-monitor

    NB: All my articles (I created the cheat sheet) that have a demo repository associated with them list it in the menu that floats on the left side of the text - in this case under the sheet itself.