Switch statement in source results in type$1.class being generated?

Remi Forax forax at univ-mlv.fr
Fri Jul 12 17:52:04 UTC 2019


Hi Davis, 

> De: "Dávid Karnok" <akarnokd at gmail.com>
> À: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> Cc: "compiler-dev" <compiler-dev at openjdk.java.net>
> Envoyé: Vendredi 12 Juillet 2019 19:37:56
> Objet: Re: Switch statement in source results in type$1.class being generated?

> Yes, that would be great. However, I seems to me I have to parse the class file
> and skip the constant pool to get to the access flags, right?

yes ! 

> Some upcoming JDK changes are planning to change that pool around, don't they?

no change is planned yet, 
the last change, the constant dynamic feature, was introduced by Java 11. 

The introduction of better generics as part of valhalla requires such changes but we are several years from that happens. 

> My current workaround is to simply scan the file for $SwitchMap$ and double
> check there is no $1$1.class, assuming such switchmap classes don't have more
> synthetic helper classes themselves.

why not using ASM [1] instead of rolling your own code ? 

Rémi 

[1] https://asm.ow2.io/ 

> Maurizio Cimadamore < [ mailto:maurizio.cimadamore at oracle.com |
> maurizio.cimadamore at oracle.com ] > ezt írta (időpont: 2019. júl. 12., P,
> 19:23):

>> On 12/07/2019 18:17, Dávid Karnok wrote:

>>> Hi Maurizio!

>>> Thanks for the clarification. I think I have some explanation why this happened.
>>> By default, I develop RxJava in Eclipse and eclipsec does not generate this
>>> file, hence the test was never tripped. I've been verifying JDKs with IntelliJ
>>> and up until 2019.1.3, the test wasn't tripped either because the compiled test
>>> classes go into separate directory than the main classes and the file was
>>> naturally not there. With 2019.2, something changed with the compilation and/or
>>> output settings and now the test could see this $1.class and failed.

>> Btw - these classes have the ACC_SYNTHETHIC flag set - so I guess it should be
>> possible for your build system to be made more robust and skip those? After
>> all, if I understand correctly, you want to catch cases where the library
>> itself is using anon inner classes - and you probably want to skip whatever
>> helper class compiler XYZ will have generated, right?

>> Maurizio

>>> In other words, a bug in the test met with a glitch/bug in the IDE made the test
>>> work as intended.

>>> Maurizio Cimadamore < [ mailto:maurizio.cimadamore at oracle.com |
>>> maurizio.cimadamore at oracle.com ] > ezt írta (időpont: 2019. júl. 12., P,
>>> 16:26):

>>>> Hi David,
>>>> javac has been generating 'switchmap' classes for enum switched since JDK 5, I
>>>> believe.

>>>> This example:

>>>> enum Foo { A, B; }

>>>> class TestSwitch {
>>>> int m(Foo foo) {
>>>> switch (foo) {
>>>> case A: return 1;
>>>> case B: return 2;
>>>> default: return -1;
>>>> }
>>>> }
>>>> }

>>>> Generates the following classes:

>>>> Foo.class
>>>> TestSwitch.class
>>>> TestSwitch$1.class

>>>> Where TestSwitch$1.class is similar to the one you have shown. I can see this
>>>> even on JDK 8.

>>>> So, I think you might have found a real issue - but I'm not sure that this
>>>> specific synthetic class is the root cause of your problem, as this class has
>>>> been there for a long time.

>>>> Maurizio
>>>> On 12/07/2019 09:30, Dávid Karnok wrote:

>>>>> Hi.

>>>>> As part of the outreach program, I'm testing the various JDK early access builds
>>>>> with the library RxJava. Now that I can test JDK 13 and JDK 14 by setting a
>>>>> version target in my IDE, I've come across a strange compiler output not
>>>>> encountered with JDK 12 and prior versions. Note that RxJava's source code uses
>>>>> Java 6 constructs only.

>>>>> One of the rules for RxJava development is that there should be no anonymous
>>>>> inner classes used as it makes analyzing stacktraces with all those $12.class
>>>>> difficult. When the project is compiled, we check for the existence of such
>>>>> type$x.class output and fail the build if found. This worked well up until JDK
>>>>> 12, but now JDK 13 and JDK 14 early accesses generate a couple of such $1.class
>>>>> files. As far as I can tell, they are due to switch statements, for example:

>>>>> [
>>>>> https://github.com/akarnokd/RxJava3_BuildMatrix/blob/master/src/main/java/io/reactivex/Observable.java#L14379
>>>>> |
>>>>> https://github.com/akarnokd/RxJava3_BuildMatrix/blob/master/src/main/java/io/reactivex/Observable.java#L14379
>>>>> ]

>>>>> switch (strategy) {
>>>>> case DROP:
>>>>> return f.onBackpressureDrop();
>>>>> case LATEST:
>>>>> return f.onBackpressureLatest();
>>>>> case MISSING:
>>>>> return f;
>>>>> case ERROR:
>>>>> return RxJavaPlugins.onAssembly(new FlowableOnBackpressureError<T>(f));
>>>>> default:
>>>>> return f.onBackpressureBuffer();
>>>>> }

>>>>> Creates Observable$1.class:

>>>>> javap Observable$1.class

>>>>> Compiled from "Observable.java"
>>>>> class io.reactivex.Observable$1 {
>>>>> static final int[] $SwitchMap$io$reactivex$BackpressureStrategy;
>>>>> static {};
>>>>> }

>>>>> Is this some kind of expected new artifact?

>>>>> --
>>>>> Best regards,
>>>>> David Karnok

>>> --
>>> Best regards,
>>> David Karnok

> --
> Best regards,
> David Karnok
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20190712/6e45052b/attachment.html>


More information about the compiler-dev mailing list