Conditional Compilation + Inner Class Oddity

Vicente-Arturo Romero-Zaldivar vicente.romero at oracle.com
Thu Oct 24 12:53:58 PDT 2013


Hi Jeremy,

The bug your are mentioning was reported in our bug DB as: "JDK-7199823: 
javac generates inner class that can't be verified" [1], the changeset 
can be accessed here [2].

Test$1 is used as a token to access the constructor of class NamedClass 
if it's private.

The issue here is that if DBG is true then an anonymous inner class 
Test$1 extending Runnable is also created. javac was reusing that class 
as the token. The problem is that if DBG is false, all the content of 
the "then" brace of the if is discarded by Lower, but as before other 
class, Check, had created Test$1 as a to-be-generated class then that 
class would be incomplete and was violating the spec as you have 
mentioned. So the fix at [2] is creating a new class if necessary and 
swaping the old unusable class extending Runnable, in this case, by a 
fresh empty class.

HTH,
Vicente.

[1] https://bugs.openjdk.java.net/browse/JDK-7199823
[2] http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/a51a8dac0a2f

On 24/10/13 19:34, Jeremy Manson wrote:
> Hi folks,
>
> We've found an oddity with conditional compilation and inner classes, 
> and was wondering if there was an explanation for it.  In the 
> following code, whether Test$1 is generated depends on whether 
> Test$NestedClass is private or not.  I don't think this violates the 
> spec (given that you don't have to generate Test$1 at all), but it is 
> deeply curious:
>
> public class Test {
>   private static final boolean DBG = false;
>
>   private
>   static class NamedClass {
>     int abc;
>   }
>
>   public void method() {
>     if (DBG) {
>       Thread t = new Thread(new Runnable() {
>           @Override public void run() {
>             System.out.println();
>           }
>         });
>     }
>     NamedClass nc = new NamedClass();
>   }
> }
>
> (Note that in javac 7, Test$1 has run() and <init> methods without 
> Code attributes, which violates the spec.  In javac 8, Test$1 doesn't 
> have run() or <init> methods at all, which is probably fine (albeit 
> odd).  Perhaps the fix should be backported?)
>
> Presumably, there is some method to the decision as to whether to 
> generate Test$1, but I have no idea what it is.
>
> Jeremy



More information about the compiler-dev mailing list