Oh, also: you say “everything else arises out of adding restrictions” as if a many capabilitties aren’t added in programming by “adding restrictions”. “Adding restrictions” is literally what type systems are about. Adding restrictions *is* how we add power in many situations. I hope and expect we’ll continue adding many more capabilities to the JDK by adding further restrictions.
> On 17 Dec 2024, at 16:12, Ron Pressler <ron.press...@oracle.com> wrote: > > To clarify, if you have a plan on how to help the maintainability and > security of your container with modules, then of course we’d be happy to > help. But using a feature when you’re not clear on how to benefit from it is > helpful to no one. I’ve seen this happen with virtual threads, too. If you > use a feature just to tick a box, then you’re unlikely to see much value in > it. You need to have a plan for how to enjoy it. > >> On 17 Dec 2024, at 16:05, Ron Pressler <ron.press...@oracle.com> wrote: >> >> >> >>> On 17 Dec 2024, at 14:21, David Lloyd <david.ll...@redhat.com> wrote: >>> >>> >>> >>> You're confusing the idea of modular encapsulation with the idea of >>> platform integrity. I'm talking specifically about the encapsulation of >>> modules that are loaded by a custom ClassLoader. If the user defines their >>> own version of a string class which purports to be immutable, and that >>> class is defined within my ClassLoader, then yes, I can mutate it if I want >>> to. There are many ways to do this. >> >> The “platform integrity” is, itself, enforced by the same module >> capabilities available to libraries. The point is that modules give you the >> ability — which didn’t exist previously — to enforce your own invariants, >> not that you can *choose* not to enforce them. The choice not to enforce >> invariants is still available, what’s new is the ability to choose to >> enforce them. >> >>> >>> When I load a module in a class loader, I can basically do whatever I want >>> with it, if I'm willing to do some tedious (and possibly >>> performance-degrading) work. All I'm proposing is to make the work of doing >>> *certain* things less tedious and performance degrading. >> >> Good, so because most programs will have just a single layer, we clearly >> have to focus on not making many modules per layer be performance-degrading. >> *That* seems to be the claimed core issue here. >> >>> >>> However, to give a counter-example, `Module` has `addUses` as well. But if >>> I want to call `addUses` on behalf of a module I've defined, there is no >>> corresponding `ModuleLayer.Controller` method so I do have to define the >>> extra class, and that's a bit silly. This is an example of an easy >>> enhancement that would not affect the integrity of the platform, would not >>> significantly increase maintenance burden (since the logic would be nearly >>> identical to its sibling methods), and would be easy to achieve. >> >> But to me this sounds like a sunk-cost argument. If the choice is between >> putting effort into supporting a rather baroque architecture, that itself is >> justified by a performance problem, wouldn’t it be better to focus on the >> performance problem, which could then support a much more common >> architecture and make the more baroque one unnecessary? >> >> If you could show how the performance issue materialises, that would be very >> helpful. >> >>> >>> >>> From our perspective, we started off with an open system, and the system >>> has been made less and less open over time. Strictly speaking, the only >>> "feature" here is fancy stack traces. Everything else arises out of adding >>> restrictions. I'm not saying this to complain about modularity, but to >>> remind you that we are presently only weakly incentivized to use modules at >>> all, so dangling intangible "benefits" before me does not entice me much. >>> We get more "features" by not using it. I'm essentially trying to be a team >>> player here, but only out of a sense of cooperation. >> >> >> But I’m not trying to entice you to use a feature which may or may not be >> appropriate for your situation. I’m only presuming that since you seem >> interested in using the feature, you’re already incentivised. >> >> Modules add powerful capabilities with very important benefits to >> maintainability and security, and will likely add more benefits. These >> benefits are available to users who wish to enjoy them. The feature doesn’t >> exist to serve itself, and using it to tick a box if you don’t believe it >> helps you certainly doesn’t help us. The JDK already enjoys these benefits. >> >>> >>> I'm not sure yet. But I think so. >> >> I would advise against that. If there’s a problem with a more >> straightforward architecture, let’s try and resolve that. >> >>> >>> Imagine a layer of 1000 modules, packaged in JAR files. To load a single >>> class from the layer, the layer must be defined. To do this, the graph must >>> be resolved, and to accomplish that, the descriptors of every module must >>> be created. To get the descriptors, each of the 1000 JAR files has to be >>> opened and the bytes of the descriptors must be read from each one. Because >>> of eager resolution, the load time of a module layer will always scale in >>> linear proportion to the potential number of modules in the layer, no >>> matter how optimized each step in the process is made to be. The only >>> possible optimization strategies involve paring down the root set - >>> something which requires ahead-of-time analysis which again would not be >>> necessary if modules were loaded and linked lazily, like classes are. >>> Loading modules on demand would solve this performance issue fairly >>> decisively; it would also not forbid ahead-of-time assembly of a module >>> graph if that is what the user wants. >> >> But the JDK has to support any reasonable number of modules in a single >> layer, as that’s the common case, anyway. There is no need to hypothesise. >> Either it works with acceptable performance or it doesn’t, and if it >> doesn’t, that requires addressing. Indeed, there’s significant ongoing >> effort on improving startup time, not just relative to modules’ current >> state, but relative to that of all Java applications, modular or otherwise. >> >> — Ron > >