Anonymous classes are not final according to reflection API
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jun 29 13:57:43 UTC 2015
Ouch. It seems like this problem existed for a very long time; the logic
used to strip away the ACC_FINAL flag from anon classes is more or less
like this:
if (c.isInner() && c.name.isEmpty()) {
flags &= ~FINAL;
}
Now, isInner() will only return true _if the class has an enclosing
instance_ which is clearly not the case if an anon class appears in a
static context.
In other words:
class Test{
void finalNo() {
new Object() { }; //ACC_FINAL not set
}
static void finalYesy() {
new Object() { }; //ACC_FINAL set here
}
}
javap Test\$1.class
Compiled from "Main.java"
class Test$1 {
final Test this$0;
Test$1(Test);
}
javap Test\$2.class
Compiled from "Main.java"
*final* class Test$2 {
Test$2();
}
I think this should be fixed so that anon classes (regardless of their
context) always have their ACC_FINAL bit unset; this is probably not
very hot from a compatibility perspective (given that it's been like
that for a long time) - but, given the consistency issue and the fact
that reflection cannot handle this anyway, I'd say we should just make
this consistent.
Thoughts?
Maurizio
On 29/06/15 14:49, Maurizio Cimadamore wrote:
> More specifically, I was talking about this related issue:
>
> https://bugs.openjdk.java.net/browse/JDK-8130032
>
> Popping back one level, I think the issue you are seeing there, is
> that ACC_FINAL is erroneosuly set by javac for diamond anon classes.
> This seems to be against all the documentation that can be found on
> JBS = example:
>
> https://bugs.openjdk.java.net/browse/JDK-8023945
>
> I seem to be able to get javac spit out ACC_FINAL reliably on JDK
> 7/8/9 - so the question is - when did it come back? Was it deliberate?
> If so, was reflection ever updated to handle this?
>
> Maurizio
>
> On 29/06/15 14:36, Remi Forax wrote:
>> yes, right,
>> it seems to be a backward compatibility land of mines.
>>
>> Rémi
>>
>> On 06/29/2015 03:29 PM, Maurizio Cimadamore wrote:
>>> I've closed it as 'not an issue' - this seems to be an outstanding
>>> issue that was fixed for some time and then reverted because of
>>> compatibility problems:
>>>
>>> https://bugs.openjdk.java.net/browse/JDK-6520152
>>>
>>> Maurizio
>>>
>>> On 23/06/15 14:42, Georgiy Rakov wrote:
>>>> I've filed the issue JDK-8129576.
>>>> <https://bugs.openjdk.java.net/browse/JDK-8129576>
>>>>
>>>> There is following issue in JBS: JDK-4777101
>>>> <https://bugs.openjdk.java.net/browse/JDK-4777101> which seems to
>>>> relate to this one.
>>>>
>>>> Thank you,
>>>> Georgiy.
>>>>
>>>> On 22.06.2015 18:56, Victor Rudometov wrote:
>>>>> This seems to be a reflection bug, since ACC_FINAL is present in
>>>>> Test12$1.class file:
>>>>>
>>>>> final class test.Test12$1 extends test.Test12$Foo<java.lang.Integer>
>>>>> minor version: 0
>>>>> major version: 52
>>>>> flags: ACC_FINAL, ACC_SUPER
>>>>>
>>>>> Thanks.
>>>>> Victor.
>>>>>
>>>>> On 22-Jun-15 18:35, Remi Forax wrote:
>>>>>> I wonder if it's not a reflection bug,
>>>>>> did you check with 'javap -c -verbose' the modifiers of the
>>>>>> generated class (something like Test12$1.class) ?
>>>>>>
>>>>>> cheers,
>>>>>> Rémi
>>>>>>
>>>>>> On 06/22/2015 05:17 PM, Georgiy Rakov wrote:
>>>>>>> Hello,
>>>>>>>
>>>>>>> if I understand correctly according to following assertion from
>>>>>>> JLS 15.9.5 anonymous classes are always final:
>>>>>>>
>>>>>>> An anonymous class is always implicitly final (§8.1.1.2).
>>>>>>>
>>>>>>> But reflection API reports that the class is not final. Namely
>>>>>>> let's consider following code:
>>>>>>>
>>>>>>> import java.lang.reflect.Modifier;
>>>>>>>
>>>>>>> public class Test12 {
>>>>>>> static class Foo<T> {}
>>>>>>>
>>>>>>> public static void main(String argv[]) {
>>>>>>> Foo<Integer> foo = new Foo<>() {};
>>>>>>> if ( (foo.getClass().getModifiers() &
>>>>>>> Modifier.FINAL) != 0 ) {
>>>>>>> System.out.println("final, modifiers: " +
>>>>>>> foo.getClass().getModifiers());
>>>>>>> } else {
>>>>>>> System.out.println("not final, modifiers: " +
>>>>>>> foo.getClass().getModifiers());
>>>>>>> }
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> On JDK9b69 it reports:
>>>>>>>
>>>>>>> not final, modifiers: 0
>>>>>>>
>>>>>>> Could you please tell if you consider this as a discrepancy
>>>>>>> between spec and javac (VM?) which should be fixed.
>>>>>>>
>>>>>>> Thank you,
>>>>>>> Georgiy.
>>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150629/55f1a95c/attachment-0001.html>
More information about the compiler-dev
mailing list