Switch statement in source results in type$1.class being generated?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jul 12 17:50:20 UTC 2019
Yes, the flags are after the constant pool. Project Valhalla will likely
add some new pool entries, but that doesn't really matter, as the
classfile has the pool size, so you can just skip past the entire thing.
That is:
skip 4 bytes (magic)
skip 2 bytes (minor version)
skip 2 bytes (major version)
u2 count = <read 2 bytes>
skip count
u2 flags = <read 2 bytes>
This should be fairly straightforward to implement, and it's stable
unless we throw the current classfile format out of the window - which I
frankly don't see happening :-)
Note that javac generates these anon class for various reasons, not just
for enum constants, so if you hardwire some $SwitchMap$ detection, be
prepared for the code to fail in other places - also we are planning
some revamp to the switch translation strategy (in preparation for
pattern matching) so these names are really not going to be stable for
much longer.
Maurizio
On 12/07/2019 18:37, Dávid Karnok wrote:
> 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? Some upcoming JDK changes are planning to change that pool
> around, don't they? 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.
>
> Maurizio Cimadamore <maurizio.cimadamore at oracle.com
> <mailto: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 <maurizio.cimadamore at oracle.com
>> <mailto: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
>>>
>>>
>>> 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/c478a786/attachment-0001.html>
More information about the compiler-dev
mailing list