On 11/6/2015 2:59 AM, Ali Ebrahimi wrote:
On Fri, Nov 6, 2015 at 4:09 AM, Alex Buckley <alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>> wrote:

    com.foo in layer2 requires com.baz in layer1, right? Yes.

    com.baz in layer1 uses types from com.bar in layer1, and NOT from
    com.bar in layer2, right? Yes.

    Therefore, com.foo uses types from com.bar in layer1 (as required by
    com.baz in layer1), right? Yes.

    I don't know what it means to say "we use com.bar@2 for layer2's
    modules". com.foo is in layer2, and you can make it read com.bar@2
    via reflection, but otherwise com.bar@2 is not read by com.foo
    because com.baz doesn't know about it.

There is no need for reflection:
Please follow this sample and test it:

layer 1: com.baz and com.bar@1
---------------------------

module com.bar {//version1
     exports com.bar;
}

------------------

//Bar.java

packagecom.bar;
public classBar {
     publicString bar(){return"bar1";}
}

module com.baz {
         requires com.bar;
         exports com.baz;
}

-----------------

//Baz.java

packagecom.baz;

importcom.bar.Bar;
public classBaz {
     publicString baz(){return newBar().bar();}
     publicBar bar(){
         return newBar();
     }
}

I expect javac will warn about the bar() method of class Baz. As a public method in a public type in an exported package, its return type is from another module (com.bar), yet module com.baz doesn't set up implied readability to that other module. Anyway, moving on.

layer 2: com.foo and com.bar@2
--------------------
module com.bar {//version2

     exports com.bar;
}

-------------

//Bar.java

packagecom.bar;

public classBar {
     publicString bar(){return"bar2";}
}

-------------

module com.foo {
         requires com.baz;

         exports com.foo;

}

-------------

Foo.java

packagecom.foo;

importcom.bar.Bar;
importcom.baz.Baz;

public classMain {
     public static voidmain(String[] args) {
         System.out.println(newBaz().baz());
         System.out.println(newBar().bar());
     }
}

Foo.java should not compile. 'import com.bar.Bar' names a type that is inaccessible from module foo. This makes the rest of the scenario moot.

public classTest {
     public static voidmain(String[] args)throwsException {
         ModuleFinder finder1 = ModuleFinder.of(Paths.get("mods1"));
         Configuration cfg1 = Configuration.resolve(finder1, 
Layer.boot(),ModuleFinder.empty(),"com.bar","com.baz");

         ModuleClassLoader cl1 =newModuleClassLoader(cfg1);
         Layer layer1 = Layer.create(cfg1, m -> cl1);

         ModuleFinder finder2 = ModuleFinder.of(Paths.get("mods2"));
         Configuration cfg2 = Configuration.resolve(finder2, 
layer1,ModuleFinder.empty(),"com.bar","com.foo");

         ModuleClassLoader cl2 =newModuleClassLoader(cl1,cfg2);
         Layer layer2 = Layer.create(cfg2, m -> cl2);



         Module foo = layer2.findModule("com.foo").get();
         Module bar2 = layer2.findModule("com.bar").get();

         Module bar1 = layer1.findModule("com.bar").get();

         ClassLoader fooModuleLoader = layer2.findLoader("com.foo");
         Class<?> mainClass = fooModuleLoader.loadClass("com.foo.Main");

         Test.class.getModule().addReads(mainClass.getModule());
         Method mainMethod = mainClass.getMethod("main", String[].class);

         mainMethod.invoke(null, (Object)newString[0]);
     }

}

Result:

bar1
bar2

As you can see com.fooreads com.bar@2 without reflection.

I say this is puzzling since with almost the equivalent code I get another 
result. If you want I can show for you in another post.

It is puzzling. By specifying com.bar@2 as one of the root modules in cfg2, you have managed to get layer2's loader to load the class com.bar.Bar from com.bar@2. And code in module foo can access that class, despite module foo not reading any com.bar module.

Even though the main class in Foo.java should not have compiled, it would have been possible to produce class com.foo.Main by other means, and the module system should be more resilient in the face of such inconsistent separate compilation. We'll have to debug this.

Alex

Reply via email to