Can't find referenced method 'java.lang.Object injectMembers(dagger.MembersInjector,java.lang.Object)
Asked Answered
B

1

10

Recently I upgrade Dagger 2.13 to 2.19, I have the below compile error at Proguard stage of this warning.

Warning: com.mypackage.MyClass_Factory: can't find referenced method 'java.lang.Object injectMembers(dagger.MembersInjector,java.lang.Object)' in program class dagger.internal.MembersInjectors

This also happens from Dagger 2.14.1 onwards. This happens only to MyClass which is in a library I include.

If I use

-dontwarn com.mypackage.MyClass_Factory

Then it will crash on runtime

java.lang.NoSuchMethodError: No static method injectMembers(Ldagger/MembersInjector;Ljava/lang/Object;)Ljava/lang/Object; in class Ldagger/internal/MembersInjectors; or its super classes (declaration of 'dagger.internal.MembersInjectors' appears in MyClass

Which means the warning from Proguard is a legit warning I should take care.

I search and found the issue is reported in https://github.com/google/dagger/pull/950#issuecomment-353223029

The solution by @ronshapiro is

You should shade the dagger.internal from one (or both) of the libraries. The old one is probably easiest

What does shade the dagger.internal means? How to solve my problem?

Bebe answered 5/11, 2018 at 14:25 Comment(1)
can you tell the solution?Icy
J
0

Shading is a part of packaging the library dependency: you'd use a rewriting tool repackage that library to include the dagger.internal from Dagger 2.13 under a new name (say librarynamehere.shaded.dagger.internal) that changes all references inside the library to use the new name. This would allow the two versions of dagger.internal to coexist in your library, but you should only try this if you can't upgrade your versions of Dagger to match in the library and in your application.


As in this answer, a refactor in Dagger 2.14 removed the method MembersInjector.injectMembers. Code generated with 2.14 and beyond shouldn't call into this method.

What's happening here is that the library you're consuming has packaged up Dagger-generated code that assumes the presence of MembersInjector.injectMembers as it was prior to 2.14. With the upgrade to 2.19, the method is absent, so the generated code is broken.

This is particularly tricky because the removal of this method is arguably a semantic versioning breaking change, but has a minor version increase that package management libraries might assume is non-breaking. In fairness to Dagger, the intent is that libraries do not ship generated code, but instead document their usage or allow the consuming application to generate code with matching libraries:

There's no guarantee that the generated code (i.e. factories) work well with each other across versions. We don't have any way of testing that. It's a generally good idea that any libraries that are intended to use Dagger in tandem are using the same version of Dagger.

If a library you don't own is passing along Dagger codegen to you and isn't documenting it, that's a bad idea on the library owners part.

If you have the option to upgrade or recompile the library with a newer version of Dagger, ideally one that matches the outer version of Dagger you're using, that would solve the problem. Likewise, if you were to keep your outer version of Dagger to match the version in the dependency. Those would be more ideal than shading.

As in the Software Engineering SE question What is a "shaded" Java dependency?, shading refers to repackaging and/or renaming a Java resource using a tool like jarjar. The idea here is to package a copy of the 2.13 dagger.internal library with the dependency, rewriting the bytecode in the library to consume the repackaged version of Dagger rather than the new one.

However, the cheapest (but most fragile) solution is "shadowing": adding a file in your source directory for dagger/internal/MembersInjectors.java matching the version of Dagger you're using but readding the missing injectMembers method. Assuming that your build system prefers local files over dependencies when setting up the classpath, your local file will be found before the Dagger-provided equivalent. This might work, but could then become a merge hazard later, and might cause weird errors if MembersInjectors changes in yet-newer versions of Dagger: I'd try this only for very temporary code.

See also: Java Class Shadowing and Shading by Ammar Khaku on Medium

Jovitta answered 31/5, 2023 at 17:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.