Implied readability + layers

Alex Buckley alex.buckley at oracle.com
Thu Nov 5 18:44:36 UTC 2015


On 11/5/2015 1:30 AM, Ali Ebrahimi wrote:
> Hi alan,
> So far quite disappointing!
>
> But I think Alex's last response on this topic says opposite of this:
>
> "We'll have to think about the implication of com.baz in layer1 sometimes
> offering a 'requires public' on com.bar in layer1, and sometimes offering a
> 'requires public' on com.bar in layer2, depending on who is reading com.baz
> in layer1."

Alan and I have discussed this. It's not possible for com.baz in layer1 
to "switch" which com.bar it depends on. There are two reasons.

First, in some loader of layer1, code in com.baz refers to a type 
exported by com.bar at 1, and thus triggers class loading of that type from 
whichever class loader in layer1 is responsible for loading com.bar at 1. 
The loader for com.baz will be marked by the JVM as an "initiating 
loader" for the type -- see JVMS8 5.3.2 -- so any further execution of 
code in com.baz that refers to the type will get the same class as 
initially loaded (from com.bar at 1). There is no way around this.

Second, when code in com.foo calls code in com.baz, the callee has no 
idea who the caller is. The bytecodes for method invocation don't pass 
that information. Since code in com.baz doesn't know the caller is 
com.foo in layer2, there is no possibility of com.baz "switching" to 
invoke code in com.bar at 2 in layer2 rather than com.bar at 1 in layer1.

It would be possible to write code in com.baz that reflectively detects 
its caller, then reflectively invokes code in either com.bar at 2 or 
com.bar at 1, never referring to exported types of any com.bar module via 
the constant pool. If you do this, good luck with all the mental 
accounting -- it's not a sane technique to build into the module system. 
Since layers can come and go, it makes sense for the module system to 
isolate code in a parent layer (com.baz in layer1) from the comings and 
goings of code in a child layer (com.bar in layer2).

> In this case adding  'requires public' on com.bar in layer2 does not mean
> we should pick com.bar at 2 for com,foo?
> This scenario would have many usages in future when world would filled with
> modules and developers would have to use newer versions of modules to fix
> bugs.
> What if com.foo compiled against com.bar at 2? adding redundant requires com.bar
> in com.foo does not help and my app will fail.
> So what is advantage of multiple layers?

Inconsistent separate compilation has caused problems at run time since 
1995. I was very clear in "Project Jigsaw: Under The Hood" that mixing 
multiple versions of a module must not be done casually.

What layers give to a managed runtime (e.g. an app server) is i) freedom 
to map modules to loaders (not only 1:1 but also n:1 and n:m), and ii) 
freedom to isolate different versions of modules from each other (see 
slide 55 in 
http://openjdk.java.net/projects/jigsaw/j1/jigsaw-under-the-hood-j1-2015.pdf).

Alex




More information about the jigsaw-dev mailing list