Confusing error message for inner non-public service provider

Peter Levart peter.levart at gmail.com
Mon Feb 13 17:08:00 UTC 2017


Hi,

Just wanted to note that the confusing javac error message is not 
specific to services and service providers.

Take the following example:

src/moda/module-info.java:

module moda {
     exports pkga;
}

src/moda/pkga/Outer.java:

package pkga;
class Outer {
     public static class Untouchable {
         public static void touch() {
             throw new AssertionError("Can't touch this!");
         }
     }
}

src/modb/module-info.java:

module modb {
     requires moda;
}

src/modb/pkgb/Intruder.java:

package pkgb;
public class Intruder {
     public static void main(String[] args) {
         pkga.Outer.Untouchable.touch();
     }
}


$ javac -d out --module-path out --module-source-path src `find src 
-name '*.java'`
src/modb/pkgb/Intruder.java:6: error: package pkga is not visible
         pkga.Outer.Untouchable.touch();
         ^
   (package pkga is declared in module moda, which does not export it to 
module modb)
1 error



Regards, Peter


On 02/09/2017 11:49 PM, Vicente Romero wrote:
> Hi Alex,
>
> Just to double check, the right javac behavior in this case should be 
> to issue similar errors in both cases like:
>
> some position here: error: ServiceImpl is not public in 
> com.example.internal; cannot be accessed from outside package
> some other position here: error: Outer.ServiceImpl is not public in 
> com.example.internal; cannot be accessed from outside package
>
> without mentioning in any case anything about visibility right?
>
> Thanks,
> Vicente
>
>
> On 02/07/2017 02:21 PM, Alex Buckley wrote:
>> On 2/7/2017 1:11 AM, Gunnar Morling wrote:
>>>      ---
>>>      package com.example;
>>>      public interface SomeService {
>>>          public void foo();
>>>      }
>>>      ---
>>>      package com.example.internal;
>>>      class Outer {
>>>
>>>          public static class ServiceImpl implements 
>>> com.example.SomeService {
>>>              public ServiceImpl() {}
>>>              public void foo() {}
>>>          }
>>>      }
>>>      ---
>>>      package com.example.internal;
>>>      class ServiceImpl implements com.example.SomeService {
>>>          public ServiceImpl() {}
>>>          public void foo() {}
>>>      }
>>>      ---
>>>      module com.example {
>>>          exports com.example;
>>>          provides com.example.SomeService with 
>>> com.example.internal.ServiceImpl;
>>>          provides com.example.SomeService with
>>> com.example.internal.Outer.ServiceImpl;
>>>      }
>>>      ---
>>>
>>> Essentially, I'm wondering:
>>>
>>> * Why Outer.ServiceImpl triggers the error about package visibility
>>> while ServiceImpl doesn't (I had a look at the EDR JLS, but I couldn't
>>> find an explanation for that, happy about any specific pointers).
>>> * Why Outer.ServiceImpl triggers "does not have a default constructor"
>>> (ServiceImpl does not). Maybe a hint would be nice that is caused by
>>> Outer not having public access.
>>
>> Thanks for showing the code. Since everything in the same module, 
>> package visibility is not relevant and javac shouldn't mention it.
>>
>> I suspect that javac is getting tripped up by the fact that 
>> Outer.ServiceImpl is declared 'public' (as the JLS and ServiceLoader 
>> both demand) but it isn't widely accessible, even within the 
>> com.example module, due to Outer's default (package) access. I 
>> believe the JLS and ServiceLoader rules are correct, so it's a javac 
>> bug.
>>
>> Alex
>



More information about the jigsaw-dev mailing list