Skip to content

Fix IncompatibleClassChangeError under Java 9 #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 25, 2018

Conversation

smarter
Copy link
Member

@smarter smarter commented Sep 17, 2017

The itf flag of visitMethodInsn and Handle in ASM needs to be true
when the method is defined in an interface. Java 8 ignores this but Java
9 fails at runtime with:
java.lang.IncompatibleClassChangeError: Method ... must be InterfaceMethodref constant

This commit is inspired by similar changes in scalac, in particular see
7d51b3f by Jason Zaugg
(from scala#5251) and
e619b03 by Lukas Rytz
(from scala#5293). This issue was also
discussed in scala#5452 (which does not
matter for Dotty since we do not run the backend optimizer).

smarter added a commit to dotty-staging/dotty that referenced this pull request Sep 17, 2017
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
@smarter
Copy link
Member Author

smarter commented Sep 17, 2017

Corresponding Dotty PR: scala/scala3#3138

@smarter
Copy link
Member Author

smarter commented Sep 17, 2017

@retronym @lrytz Maybe you have some idea on the root cause requiring 48e0589. How does Scalac handle static methods on interfaces? Is the receiver the companion object created by ClassfileParser too?

smarter added a commit to dotty-staging/dotty that referenced this pull request Sep 17, 2017
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
@smarter smarter changed the title Fix IncompatibleClassChangeError under Java 9 [WIP] Fix IncompatibleClassChangeError under Java 9 Sep 17, 2017
@retronym
Copy link

Scalac 2.12.3 emits an InterfaceMethodRef

⚡ (java_use 9; cat sandbox/test.scala; scalac sandbox/test.scala && javap -c C.class; java Test )
object Test { def main(args: Array[String]): Unit = java.util.List.of("", "") }

Compiled from "test.scala"
public class C {
  public void main(java.lang.String[]);
    Code:
       0: ldc           #13                 // String
       2: ldc           #13                 // String
       4: invokestatic  #19                 // InterfaceMethod java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
       7: pop
       8: return

  public C();
    Code:
       0: aload_0
       1: invokespecial #26                 // Method java/lang/Object."<init>":()V
       4: return
}

See:

https://github.com/scala/scala/blob/32f597704698291b7162335844b366a20873c67b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala#L332-L335

https://github.com/scala/scala/blob/3347b806adecfbf663e7db4e1962504d9b106b83/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala#L677

https://github.com/scala/scala/blob/3347b806adecfbf663e7db4e1962504d9b106b83/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala#L1077-L1098

@smarter
Copy link
Member Author

smarter commented Sep 18, 2017

Thanks! I guess this answers my question: https://github.com/scala/scala/blob/32f597704698291b7162335844b366a20873c67b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala#L76-L79, you're calling isInterface on a representation which already takes care of getting rid of companion objects.

smarter added a commit to dotty-staging/dotty that referenced this pull request Oct 12, 2017
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
smarter added a commit to dotty-staging/dotty that referenced this pull request Oct 12, 2017
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
smarter added a commit to dotty-staging/dotty that referenced this pull request Oct 12, 2017
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
The itf flag of `visitMethodInsn` and `Handle` in ASM needs to be true
when the method is defined in an interface. Java 8 ignores this but Java
9 fails at runtime with:
java.lang.IncompatibleClassChangeError: Method ... must beInterfaceMethodref constant

This commit is inspired by similar changes in scalac, in particular see
7d51b3f by Jason Zaugg
(from scala#5251) and
e619b03 by Lukas Rytz
(from scala#5293). This issue was also
discussed in scala#5452 (which does not
matter for Dotty since we do not run the backend optimizer).
smarter added a commit to dotty-staging/dotty that referenced this pull request Aug 23, 2018
This commit temporarily changes .gitmodules until
lampepfl/scala#24 is merged.
@smarter smarter changed the title [WIP] Fix IncompatibleClassChangeError under Java 9 Fix IncompatibleClassChangeError under Java 9 Aug 24, 2018
@smarter smarter requested a review from allanrenucci August 24, 2018 13:05
@smarter smarter assigned allanrenucci and unassigned smarter Aug 24, 2018
@smarter smarter merged commit 3fe7950 into lampepfl:sharing-backend Aug 25, 2018
@allanrenucci allanrenucci deleted the fix-java9-itf branch August 25, 2018 07:46
nicolasstucki pushed a commit to dotty-staging/scala that referenced this pull request Jul 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants