ALL-UNNAMED module does not export all packages from classpath

Jonathan Gibbons jonathan.gibbons at oracle.com
Mon Mar 20 22:31:16 UTC 2017


Pavel,

It looks like you have tripped over an issue in javac's handling of an 
automatic module, and its ability to read classes from the unnamed 
module (i.e. classpath).

-- Jon


On 03/20/2017 03:19 PM, Pavel Bucek wrote:
> Hi Alex,
>
> The usecase is about compiling tests in maven projects.
>
> I mirrored the content of the zip to github: 
> https://github.com/pavelbucek/reproducer (project contains useful README)
>
> The TestCase.java [1] contains simple testcase, compilable when 
> everything is on the classpath.
>
> When module-info.java is added to the standard sources of a maven 
> module, the compilation changes from "put everything on classpath" to 
> "put test dependencies on classpath, standard dependencies on module 
> path", which results in:
>
> javac -d target/test-classes -classpath 
> lib/junit-4.12.jar:lib/hamcrest-core-1.3.jar:lib/mockito-core-2.7.17.jar:lib/byte-buddy-1.6.11.jar:lib/byte-buddy-agent-1.6.11.jar:lib/objenesis-2.5.jar 
> --module-path target/classes -target 9 -source 9 -Xmodule:tst 
> --add-reads tst=ALL-UNNAMED src/test/java/tst/TestCase.java
>
> Test classes are effectively "patched" into main module (here called 
> "tst") and the module requires "ALL-UNNAMED", to be able to use test 
> dependencies.
>
> I'm not sure about exact cause, but seems like the ALL-UNNAMED module 
> doesn't automatically export all packages, only those which were 
> analyzed as required by some other module.
>
> When TestCase.java doesn't "import 
> org.mockito.stubbing.OngoingStubbing", classpath compilation is ok, 
> since we are not using that type directly. But it is part of the 
> fluent builder pattern, used on line 18 [2]. If there is a mechanism 
> which decides which package is required, it omitted the return type of 
> called "when" method, which caused the error. When the package is 
> explicitly imported, the error is gone and compilation proceeds as 
> expected.
>
> Regards,
> Pavel
>
>
> [1] 
> https://github.com/pavelbucek/reproducer/blob/master/src/test/java/tst/TestCase.java
> [2] 
> https://github.com/pavelbucek/reproducer/blob/master/src/test/java/tst/TestCase.java#L18
>
>
> On 20/03/2017 22:56, Alex Buckley wrote:
>> I can't figure out which classes are on which path, and why you think 
>> ALL-UNNAMED should export FROM the classpath when its purpose is to 
>> export TO the classpath.
>>
>> Please clarify your configuration in a few short sentences, rather 
>> than asking us to open a zip file on an unknown host.
>>
>> Alex
>>
>> On 3/20/2017 2:44 PM, Pavel Bucek wrote:
>>> // moving from jdk9-dev, as suggested.
>>>
>>> Hi Jon,
>>>
>>> Thanks for clarification of the error message.
>>>
>>> The main point here is that adding "import ... " fixes the issue, which
>>> doesn't feel correct.
>>>
>>> When dependencies are put on the classpath, the import statement is not
>>> required.
>>>
>>> Regards,
>>> Pavel
>>>
>>> On 20/03/2017 22:26, Jonathan Gibbons wrote:
>>>> If nothing else, the javac error message needs work.
>>>>
>>>>> (package org.mockito.stubbing is declared in module , which does not
>>>>> export it)
>>>>
>>>> The space between "module" and "," means there's an "empty" module
>>>> name there, for the unnamed module, which should have been stated
>>>> explicitly (i.e. "declared in the unnamed module").
>>>>
>>>> Follow-ups would be better on jigsaw-dev or compiler-dev.
>>>>
>>>> -- Jon
>>>>
>>>>
>>>>
>>>> On 03/20/2017 02:15 PM, Libor Kramolis wrote:
>>>>> Hello.
>>>>>
>>>>> I have problem to compile following unit test:
>>>>> import org.junit.Test;
>>>>> import static org.junit.Assert.assertEquals;
>>>>> import static org.mockito.ArgumentMatchers.any;
>>>>> import static org.mockito.Mockito.mock;
>>>>> import static org.mockito.Mockito.when;
>>>>>
>>>>> public class TestCase {
>>>>>
>>>>>      @Test
>>>>>      public void test() {
>>>>>          Context context = mock(Context.class);
>>>>>          when(context.test(any())) //returns
>>>>> org.mockito.stubbing.OngoingStubbing
>>>>>                  .thenReturn("mock");
>>>>>
>>>>>          assertEquals("mock", context.test("any"));
>>>>>      }
>>>>>
>>>>>      interface Context {
>>>>>          String test(String value);
>>>>>      }
>>>>>
>>>>> }
>>>>> with following error:
>>>>>
>>>>> src/test/java/tst/TestCase.java:15: error:
>>>>> OngoingStubbing.thenReturn(T,T...) in package org.mockito.stubbing is
>>>>> not accessible
>>>>>                  .thenReturn("mock");
>>>>>                  ^
>>>>>    (package org.mockito.stubbing is declared in module , which does
>>>>> not export it)
>>>>>    where T is a type-variable:
>>>>>      T extends Object declared in interface OngoingStubbing
>>>>> 1 error
>>>>>
>>>>> Interface org.mockito.stubbing.OngoingStubbing is returned by when(…)
>>>>> method. And whenever I explicitly import the interface (no other
>>>>> change in code is necessary) compilation works.
>>>>>
>>>>> Full reproduced sources are available in zip file at
>>>>> http://anise.cz/~paja/liba/reproducer.zip
>>>>> <http://anise.cz/~paja/liba/reproducer.zip>. It contains javac
>>>>> commands. It is also possible to build it by Maven.
>>>>>
>>>>> What do you think about this behaviour? It seems to me as a bug. The
>>>>> import statement is very artificial in this case.
>>>>>
>>>>> Thanks in advance for your help.
>>>>>
>>>>> Best regards,
>>>>> Libor
>>>>
>>>
>



More information about the jigsaw-dev mailing list