Recently I was debugging a case of NoSuchMethodError
when using the Google Guava library. Conceptually my code was doing the following:
1 |
Preconditions.checkNotNull(someObject, "Some string with %s formatting", "parameter") |
In runtime I was using library in version 19 and I was getting the following error:
1 2 3 |
java.lang.IllegalStateException: Failed to load ApplicationContext ... Caused by: java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkNotNull(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; |
I decompiled the code and got something similar to this
1 2 3 4 5 6 7 8 |
public static < T> T checkNotNull( T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) { if (reference == null) { // If either of these parameters is null, the right thing happens anyway throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); } return reference; } |
If you look closely you can see that the error is correct. The method mentioned in the stacktrace does not exist. Why? Because the method in the source code has different third parameter. It is not Object
but effectively Object[]
as varargs are compiled to arrays.
So the question is: why did my code try to call different method even though there is no other method with similar signature? I immediately suspected that there must be other Guava jar in different version with method matching the error. And I was right, the code was compiled with latest version which has the following
1 2 3 4 5 6 7 |
public static < T> T checkNotNull( T obj, @Nullable String errorMessageTemplate, @Nullable Object p1) { if (obj == null) { throw new NullPointerException(lenientFormat(errorMessageTemplate, p1)); } return obj; } |
Tu sum up — code was compiled with latest version of Guava which has “overload” for three parameters. This is an interesting case of source compatibility but not the binary compatibility between versions. After changing runtime library to the latest version the error was gone.