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

Michael Rasmussen Michael.Rasmussen at roguewave.com
Mon Jul 15 12:56:42 UTC 2019


Just an FYI.


the Eclipse Java compiler also created SwitchMap classes, but they are slightly different, and use a different naming pattern, they use $SWITCH_TABLE$ instead.


/Michael

________________________________
From: compiler-dev <compiler-dev-bounces at openjdk.java.net> on behalf of Dávid Karnok <akarnokd at gmail.com>
Sent: 12 July 2019 20:37:56
To: Maurizio Cimadamore
Cc: compiler-dev at openjdk.java.net
Subject: 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? 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/20190715/5427825e/attachment.html>


More information about the compiler-dev mailing list