Skip to content

IllegalAccessError: tried to access class io.vavr.Lambda from class Main$ #2337

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

Closed
2m opened this issue Jan 12, 2019 · 12 comments
Closed

IllegalAccessError: tried to access class io.vavr.Lambda from class Main$ #2337

2m opened this issue Jan 12, 2019 · 12 comments
Labels

Comments

@2m
Copy link

2m commented Jan 12, 2019

When using vavr 0.9.3 with Scala 2.12.7 I am getting the following exception:

java.lang.BootstrapMethodError: java.lang.IllegalAccessError: tried to access class io.vavr.Lambda from class Main$
        at Main$.main(Main.scala:3)
        at Main.main(Main.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:99)
        at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:34)
        at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:30)
        at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:125)
        at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:99)
        at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:91)
        at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:125)
        at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:22)
        at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:21)
        at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
        at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:29)
        at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:28)
        at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
        at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:66)
        at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85)
        at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
        at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

When trying to run the following code:

object Main {
  def main(args: Array[String]): Unit = {
    println(io.vavr.Function1.of(math.abs))
  }
}

I compile and run the code with the following commands:

scalac -d out -classpath (coursier fetch io.vavr:vavr:0.9.3 | paste -s -d:) Main.scala
scala -d out -classpath out:(coursier fetch io.vavr:vavr:0.9.3 | paste -s -d:) Main

The compiled class according to javap looks like:

vavr-interop ─╼ javap -c out/Main\$.class                                                                                                                                                             0
Compiled from "Main.scala"
public final class Main$ {
  public static Main$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class Main$
       3: invokespecial #17                 // Method "<init>":()V
       6: return

  public void main(java.lang.String[]);
    Code:
       0: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       3: invokedynamic #49,  0             // InvokeDynamic #0:apply:()Lio/vavr/Function1;
       8: invokestatic  #55                 // InterfaceMethod io/vavr/Function1.of:(Lio/vavr/Function1;)Lio/vavr/Function1;
      11: invokevirtual #59                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      14: return

  public static final int $anonfun$main$1(int);
    Code:
       0: getstatic     #69                 // Field scala/math/package$.MODULE$:Lscala/math/package$;
       3: iload_0
       4: invokevirtual #72                 // Method scala/math/package$.abs:(I)I
       7: ireturn

  public static final java.lang.Object $anonfun$main$1$adapted(java.lang.Object);
    Code:
       0: aload_0
       1: invokestatic  #82                 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
       4: invokestatic  #84                 // Method $anonfun$main$1:(I)I
       7: invokestatic  #88                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      10: areturn
}
@2m
Copy link
Author

2m commented Jan 13, 2019

I noticed that this error does not occur with older Scala versions, like 2.12.4. Therefore I should better report this to Scala issue tracker.

@danieldietrich
Copy link
Contributor

Hi,

thank you for reporting the issue!

Lambda is a package-private class, which will disappear in vavr-1.0.
I'm about to release vavr-0.10.0, so I will fix that.

Does the error also occur with Scala 2.13.0-M5?

Thanks!

@2m
Copy link
Author

2m commented Jan 13, 2019

Yes, same error with 2.13.0-M5. Looks like 2.12.4 is the last version that works.

@danieldietrich
Copy link
Contributor

danieldietrich commented Jan 14, 2019

Thank you for your feedback, that helps!

Btw - I did not know about coursier, that is really an awesome way of setting the classpath!

I could reproduce the problem but I needed to tweak your scripts a bit:

- scalac -d out -classpath (coursier fetch io.vavr:vavr:0.9.3 | paste -s -d:) Main.scala
+ scalac -d out -classpath "$(coursier fetch -p io.vavr:vavr:0.9.3)" Main.scala
- scala -d out -classpath out:(coursier fetch io.vavr:vavr:0.9.3 | paste -s -d:) Main
+ scala -d out -classpath out:"$(coursier fetch -p io.vavr:vavr:0.9.3)" Main

I will give you an update the next days...

@2m
Copy link
Author

2m commented Jan 14, 2019

Yes, coursier is quite neat. :) I am using fish as my shell, therefore the difference of the shells scripts.

@danieldietrich
Copy link
Contributor

Aha! :)

@danieldietrich
Copy link
Contributor

danieldietrich commented Jan 17, 2019

Ok, it runs now on my local machine, using a local build of vavr-0.10.0-SNAPSHOT.

vavr-on-scala

I will re-test it with the final build before release.

@danieldietrich
Copy link
Contributor

Update: Sorry, I used the wrong example. It does still not work.

object Main {
  def main(args: Array[String]): Unit = {
    // does work :)
    val f: java.util.function.Function[Int, Int] = i => i
    // does not work :/
    val f2: io.vavr.Function1[Int, Int] = i => i
  }
}

Error:

Caused by: java.lang.invoke.LambdaConversionException: Type mismatch for instantiated parameter 0: class java.lang.Object is not a subtype of interface java.util.function.Function
        at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:308)
        at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:296)
        at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:503)
        at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138)

Maybe this error occurs, because Vavr's Function1 extends j.u.f.Function and scala is confused about that. 🤔


The current SNAPSHOT can be tested here:

#!/bin/bash

DEPS=`coursier fetch -r https://oss.sonatype.org/content/repositories/snapshots/ -p io.vavr:vavr:0.10.0-SNAPSHOT`

scalac -d out -classpath $DEPS Main.scala

scala -classpath out:$DEPS Main

@danieldietrich
Copy link
Contributor

As you said, it could be that Scala introduced a bug in recent versions regarding creation/handling of Lambda MetaFactories, MethodHandles.Lookup etc - it worked before...

It would be interesting to reproduce it with a minimal non-Vavr functional interface.

@danieldietrich
Copy link
Contributor

danieldietrich commented Jan 19, 2019

I do some further tests.

Testee

I use the following testee, because it failed to compile with Vavr (see above).

object Main {
  def main(args: Array[String]): Unit = {
    val f: test.FI[Int, Int] = i => i
  }
}

I compile the test the following way (using JDK8 and JDK11):

javac -cp . ./test/FI.java
scalac -d out -classpath . Main.scala
scala -classpath out:. Main

✅ Extending a functional interface

A custom Java functional interface (fi) that extends a Java standard lib fi works fine with Scala:

// file FI.java
package test;

@FunctionalInterface
public interface FI<T, R> extends java.util.function.Function<T, R> {
    @Override
    R apply(T t);
}

✅ Internally using an auxiliary interface

// file FI.java
package test;

@FunctionalInterface
public interface FI<T, R> {

    static <T, R> FI<T, R> of(FI<T, R> f) {
        return (FI<T, R> & Internal) f;
    }

    R apply(T t);
}

interface Internal {
}

✅ Internally using package private interface

// file FI.java
package test;

@FunctionalInterface
public interface FI<T, R> {

    static <T, R> FI<T, R> of(FI<T, R> f) {
        return (FI<T, R> & Pkgprivate) f;
    }

    R apply(T t);
}
// file Pkgprivate.java
package test;

interface Pkgprivate {
}

✅ Serializable functional interface

// file FI.java
package test;

@FunctionalInterface
public interface FI<T, R> extends java.io.Serializable {

    long serialVersionUID = 1L;
    
    R apply(T t);
}

@danieldietrich
Copy link
Contributor

@2m I found a minimal Java-only example and filed a Scala bug: scala/bug#11373
Thx!

@2m
Copy link
Author

2m commented Jan 20, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants