Confusing error message for inner non-public service provider
Peter Levart
peter.levart at gmail.com
Tue Feb 14 08:00:47 UTC 2017
Hi Jon,
I understand that service providers have a different set of rules (they
are usually not universally accessible classes) and therefore the
requirement for them to have public access modifier is merely a choice
JLS made to enforce a certain degree of strictness. Classes with default
(package-private) modifier could easily be allowed too, but I guess some
strictness is welcome. I just wanted to share what I observed: that the
javac error message is similar also when trying to access a public
nested class in a package-private enclosing class in an exported
package, from a different module, which has nothing to do with service
providers.
Regards, Peter
On 02/13/2017 08:10 PM, Jonathan Gibbons wrote:
> Peter,
>
> The circumstances of the analysis of service providers are very
> different to the normal JLS rules regarding visibility and
> accessibility of named items.
>
> I know that we have some cleanup to do, for javac to "catch up" with
> the latest updates to JLS, especially with regards to the difference
> between "visibility" and "accessibility". Is that the issue you
> concerned about, or is there something else about this message you
> find confusing.
>
> -- Jon
>
> On 02/13/2017 09:08 AM, Peter Levart wrote:
>> 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