> 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

Reply via email to