Closed naixx closed 10 years ago
Thanks. I was able to reproduce it. I'll have a look at solving it soon, maybe tomorrow.
I'm guessing that this has something to do with how in Java 8 the lambda classes have some special handling to that they can call private methods of other classes. Retrolamdba should probably detect when a method reference targets a private method and make it package private.
This isn't a Dalvik specific problem, so I renamed the issue.
Great to hear, that the problem is identified!
Still one bug remains (seems to depend on JDK 8 build). Working on it...
The fix is included in Retrolambda 1.2.2. It should show up in Maven Central in a couple of hours.
Looks like magic, thanks!
Hello, @orfjackal !
After updating to the new version, I've catched a crash.
@Test
public void call_of_method_with_reference(){
class InnerClass {
void foo(){
Runnable r = LambdaTest.this::privateVoidMethod;
r.run();
}
}
new InnerClass().foo();
privateVoidMethod();
assertThat(privateInstanceMethod(), is("foo"));
}
The code structure is like this. I haven't checked it in a test.
Please submit a SSCCE. You example doesn't compile and I haven't managed to reproduce the problem.
@orfjackal ok, finally I managed to reproduce the problem.
void thisMethodIsAlsoReferenced() {
Observable.from("foo").lift((Operator<String, String>) (subscriber) -> {
Runnable ref = MyOuterClass.this::problemPrivateMethod; //we make a reference in an anonymous class
ref.run();
return subscriber;
}).subscribe(s -> {
L.e(s);
});
problemPrivateMethod(); //java.lang.NoSuchMethodError
}
Unfortunately, I can't reproduce the problem in tests.
Please make that example short and self contained (http://www.sscce.org/) so that I can run it. Or send the me .class files before and after processing that code with Retrolambda.
Does the problem happen with Oracle JVM or only Dalvik VM?
I tried to make a simple junit test in a fork of your repo, but the problem didn't appear in that case. The only way to reproduce is run on Android device.
https://github.com/naixx/PrivateMethodAndroidBug Here is an Android project, that reproduces the problem with Davlik VM. I hope it matches SSCCE a bit :)
The warnings I get:
I/dalvikvm﹕ Could not find method com.example.testbug.app.MainActivity.problemPrivateMethod, referenced from method com.example.testbug.app.MainActivity.methodCall
W/dalvikvm﹕ VFY: unable to resolve direct method 8443: Lcom/example/testbug/app/MainActivity;.problemPrivateMethod ()V
And error on method usage.
I've also added classes before and after retrolambda from a real project. The problem method is cleanup and problemPrivateMethod
How to run that project? I can compile it with gradlew clean build
but I haven't done any Android development and I can't figure out the command for starting the application.
If you don't have device, the easiest way is to run it through emulator or Genymotion. After build to run it on device or emulator type adb install ResultedFile.apk
.
You can also try Android Studio for that propose. It is the simplest way.
I hope, this can help.
Thanks. I was able to reproduce it. Let's continue discussion in #18
Hi. The problem is:
The code is compiled and dexed to run on Davlik VM. But in runtime on an android device I get warnings and the method isn't called, of course.
The code works as a lambda if
myProblemMethod
is package private, public, everything except private. The method can be called explicitly. But it doesn't work as a method reference. Warnings appear only once.So, is it a problem, that retrolambda somehow processes references, so that dex excludes them from the build?