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@1, and thus triggers class loading of that type from whichever class loader in layer1 is responsible for loading com.bar@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@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@2 in layer2 rather than com.bar@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@2 or com.bar@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@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@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


Reply via email to