-
Notifications
You must be signed in to change notification settings - Fork 227
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
Problems with backported default and static methods #48
Comments
Does it work when you do a clean build? Please post the resulting .class files regarding those error messages. |
All test are done by cleaning the whole project every time otherwise I obtain: I replicated the errors in this very simple project with only two Java files. The obfuscation error is exaclty the same, the second error is instead: java.lang.ClassFormatError: Class file version does not support constant tag 15 in class file test/Interface$ I'm trying to post them here but it doesn't allow me, you can find them there http://pastebin.com/wdeq3HNY |
Thanks. I had missed the possibility of having lambda expressions inside default methods and static methods on interfaces. Please try again with Retrolambda 2.0.1 and tell me if it works now. (It may take a couple of hours for 2.0.1 to show up in Maven Central, but in the meanwhile you can get it from the https://oss.sonatype.org/content/groups/public/ repository.) |
Hi, thanks for the reply. The error is: Note that if I remove any method (e.g., getFalse() or toSupplier()) from the interface the obfuscation is successful. Only with all the methods (2 static and 2 default methods) it fails. |
Hmm. I can't get it to fail on just Java, so it's something obfuscation related. I found one possible source of confusion for proguard: some generic method signatures were not updated to match their erased method descriptor. Please try if this build fixes the problem: https://oss.sonatype.org/content/groups/public/net/orfjackal/retrolambda/retrolambda/2.0.2-SNAPSHOT/retrolambda-2.0.2-20150408.191342-1.jar |
What are your ProGuard settings? I tried processing your example classes with ProGuard, using the default settings in proguardgui.jar, but did not get any warnings about that. There's a possibly non-deterministic hack in Retrolambda which causes lambdas in interfaces to be backported twice, but I would like to reproduce this issue before attempting to fix that hack (especially if it's not the root cause). |
No, unfortunately the error is the same. [java] Warning: test.BooleanSupplier$: can't find referenced method 'test.BooleanSupplier lambdaFactory$(test.BooleanSupplier)' in program class test.BooleanSupplier$$Lambda$4 If it can help, I decompiled the generated code and found that in the specified class (test.BooleanSupplier$$Lambda$4) there isn't such a method, but there is a similar one: Note that, as I wrote in the other post, if I remove any method it works, if I decompile class test.BooleanSupplier$$Lambda$4 I find: So the method exists when changing the source file, that's the reason it works. With the exact source as I posted the method is instead missing. Thanks for your time and for retrolambda. |
Thanks. The mixing up of Lambda$4 and Lambda$2 seems to suggest that the cause is the hack I mentioned earlier. I'll have a look at solving it. |
This is the proguard configuration: http://pastebin.com/KTi8Fgup |
…ith the erased method descriptor Relates to issue #48
I'm unable to reproduce this on my machine, so please try if snapshot fixes it for you: https://oss.sonatype.org/content/groups/public/net/orfjackal/retrolambda/retrolambda/2.0.2-SNAPSHOT/retrolambda-2.0.2-20150408.201435-2.jar |
The test project now obfuscate fine, but coming back to the main library it still gives a lot of errors: [java] Warning: org.plibrary.dao.DAOObject$$Lambda$1: can't find referenced method 'boolean lambda$xor$39(org.plibrary.compat.Predicate,org.plibrary.compat.Predicate,java.lang.Object)' in program class org.plibrary.compat.Predicate$ If I decompile the class it has only the method: All the errors refers to methods with number, but no number in generated classes. I do not know it it is related to the other bug Tomorrow I'll prepare a runnable package with all the requirements to reproduce on other machines :-) |
Are you sure that you decompiled |
Strange, with javap I have
but decompiling the sources with jd-gui gives me no numbers. I need to make something you can replicate. |
I wonder whether the error is because that the method is package-private, but it appears to be used from another package. Please send me the .class files |
Here is a snapshot build that will make that method public, but the real fix would be to not generate the method that calls it in the first place. Try whether this one fixes it and whether there are still more problems. I'll work on a proper fix tomorrow or later this week. |
You are definitely right. The problem is that proguard can't find the package-private methods. I replicated the error by simply using a lambda from a class in another package. Here you find the whole test project with sources, classes, proguard jar and an executable batch to launch obfuscation which will cause the error (change the rt.jar path). |
This is now fixed in Retrolambda 2.0.2. This one issue covered 4 different bugs. 😅 If you still find more, please create a new issue. |
OK it works. Sorry for the multiple requests but at the beginning I thought all bugs were related. |
No problem. They all were related to the new default methods feature. I expected some bugs to remain in v2.0.0, due to the huge amount of language features which may possibly interact with default methods, but even then was surprised at how many bugs there were. 😆 |
I think I still see this issue: Proguard seems to shrink methods, referenced as method references. See an example below: public class AsyncTaskBuilder<Progress, Result> {
public interface BackgroundWorkWithProgress<_Progress, _Result> {
_Result execute(ProgressObserver<_Progress> progressObserver);
}
private BackgroundWorkWithProgress<Progress, Result> work;
public AsyncTask<Void, Progress, Result> build() {
return new AsyncTask<Void, Progress, Result>() {
@Override
protected Result doInBackground(Void... voids) {
// this reference will not be taken into account by Proguard
return work.execute(this::publishProgress);
}
};
}
} After building, the following error is shown:
Full log is available at travis-ci Simple android project (with 1 class), reproducing the issue can be found here: |
I'm trying to backport some default and static methods with new version 2.0.
PRE: The project I'm backporting is successfully backported with old version of retrolambda if I remove all default and static method. The project is also obfuscated with proguard 5.1 successfully.
When trying the new version I have two problems:
[java] Warning: org.plibrary.test.TestLinq$$Lambda$55: can't find referenced method 'boolean lambda$negate$38(org.plibrary.compat.Predicate,java.lang.Object)' in program class org.plibrary.compat.Predicate$
Note that "negate" is the name of the default method but no class has been generated with that name
initializationError(org.plibrary.test.TestLinq)
java.lang.ClassFormatError: Method lambda$and$27 in class org/plibrary/compat/Consumer has illegal modifiers: 0x1402
"and" is another default method and Consumer is an interface.
As an additional info these are the options I'm using as printed by retrolambda
[java] Retrolambda 2.0.0
[java] Bytecode version: 50 (Java 6)
[java] Default methods: true
[java] Input directory: build\classes
[java] Output directory: build\classes
I tried also with bytecode 51, nothing changes.
Any idea of what I can do?
Thanks.
The text was updated successfully, but these errors were encountered: