VerifyError on Kitkat when code explicitly calls a default method - java

When instantiating a class that has code to explicitly call a default method for an interface that it implements, a java.lang.VerifyError is thrown. This happens on Kitkat (API 19), but Lollipop and more recent versions work fine. The default method I'm working with was added in Android 12 (API 31), but I have a build version check, so that line won't even execute on earlier versions, but Kitkat still throws the error.
public class MyInputConnection implements InputConnection {
private void foo() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
SurroundingText surroundingText = InputConnection.super.getSurroundingText(1, 1, 0);
//...
}
}
}
MyInputConnection ic = new MyInputConnection(this); // error thrown here
Logs before the error:
W/dalvikvm: DexOpt: method is in an interface
I/dalvikvm: Could not find method android.view.inputmethod.InputConnection.getSurroundingText, referenced from method com.ewittman.example.MyInputConnection.foo
W/dalvikvm: VFY: unable to resolve virtual method 44: Landroid/view/inputmethod/InputConnection;.getSurroundingText (III)Landroid/view/inputmethod/SurroundingText;
VFY: rejecting opcode 0x6f at 0x0008
VFY: rejected Lcom/ewittman/example/MyInputConnection;.foo ()V
Verifier rejected class Lcom/ewittman/example/MyInputConnection;
Error:
java.lang.VerifyError: com/ewittman/example/MyInputConnection
Why is this error getting thrown on Kitkat? Since the line of code to call the default method won't even be executed on Kitkat, I'd expect the class to instantiate without error.
I could create a new dummy implementation of the interface that doesn't override the default method so I can call that, but that doesn't seem like a very clean solution. Is there a better way to allow directly calling the default method for versions that include the method that won't break older versions?

Related

Proguard error: "Can't find common super class of ..."

I'm getting this error while building my app in Android Studio:
Unexpected error while performing partial evaluation:
Class = [com/google/android/gms/internal/zznc]
Method = [zza(Lcom/google/android/gms/internal/zzmk;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/google/android/gms/internal/zznh;Lcom/google/android/gms/internal/zzgl;Lcom/google/android/gms/internal/zznb;)Lcom/google/android/gms/internal/zzmn;]
Exception = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/android/gms/internal/zzmn] (with 1 known super classes) and [java/lang/String] (with 2 known super classes))
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Can't find common super class of [com/google/android/gms/internal/zzmn] (with 1 known super classes) and [java/lang/String] (with 2 known super classes)
:analytics_test_app:transformClassesAndResourcesWithProguardForDebug FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':analytics_test_app:transformClassesAndResourcesWithProguardForDebug'.
> Job failed, see logs for details
How can I solve that?
Do you have different versions of different Play Service libraries? Make sure you use the same version for all libraries:
implementation 'com.google.android.gms:play-services-analytics:16.0.1'
implementation 'com.google.android.gms:play-services-auth:11.8.0' // should be the same version
Some versions have different implementations and APIs, which causes internal conflicts that also affects Proguard.

Unity AndroidJNI resolves classes but not methods

I am trying to interface with native Android methods from C# in Unity using AndroidJNI, however I can only resolve classes, not methods.
I have also used the 'simpler variants', meaning AndroidJavaClass interface, but the error says its trying to resolve the methods from java.lang.Object, therefore I moved onto using AndroidJNI, but am stuck resolving the methods.
I have the following java method
public static String getParamsString2() {
return "asd";
}
and the following c# code trying to resolve the method id
AndroidJNI.GetStaticMethodID(activityClass, "getParamsString2", "()Ljava/lang/String;");
I have verified from the decompiler that the signature is correct, however I end up receiving the following error
java.lang.NoSuchMethodError: no static method "Lfi/matalamaki/plugin/UnityPlayerActivity;.getParamsString2()Ljava/lang/String;
When I decompile the class there actually is the class which contains the method
public static getParamsString2() { //()Ljava/lang/String;
L1 {
ldc "asd" (java.lang.String)
areturn
}
}
The class is also correct, fi/matalamaki/plugin/UnityPlayerActivity
when using the AndroidJavaClass interface with code
string referrer3 = new AndroidJavaClass("fi.matalamaki.plugin.UnityPlayerActivity").CallStatic<string>("getParamsString2", new object[0]);
I get the following error AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='getParamsString2' signature='()Ljava/lang/String;' in class Ljava.lang.Object;
java.lang.NoSuchMethodError: no static method with name='getParamsString2' signature='()Ljava/lang/String;' in class Ljava.lang.Object;
which seems to indicate that its trying to resolve the method from java.lang.Object instead of my own class..
I've tried different parameter and return type combinations but no luck..
I've also verified the built APK dex by decompiling it..
Apparently it was Proguard that by minifying or by obfuscating removed the method or renamed it. I have no idea how after verifying I saw the method there, but maybe I wasn't paying enough attention, and it had its name changed or so.
After adding a proguard exclusion on my package and its fields and methods the problem is now solved.

NoSuchMethodError on inherited method

I'm trying to run a package that has dependencies on several hundred packages and I keep getting the following error:
Caused by: java.lang.NoSuchMethodError: com.company.jacksonion.JoiObjectMapper.setSerializationInclusion(Lorg/codehaus/jackson/map/annotate/JsonSerialize$Inclusion;)Lorg/codehaus/jackson/map/ObjectMapper;
at com.company.raft.utils.IonUtil.createJacksonIonMapper(IonUtil.java:33)
at com.company.raft.utils.IonUtil.<clinit>(IonUtil.java:40)
at com.company.raft.i18n.MarketplaceManager.loadFromFile(MarketplaceManager.java:96)
at com.company.raft.i18n.MarketplaceManager.loadAllConfigs(MarketplaceManager.java:55)
at com.company.raft.env.EnvManager.<init>(EnvManager.java:118)
at com.company.raft.env.EnvManager.instance(EnvManager.java:147)
at com.company.raft.bases.AbstractTestBase.<init>(AbstractTestBase.java:49)
at com.company.product.peekaboo.test.bases.PeekabooTestBase.<init>(PeekabooTestBase.java:38)
at com.company.product.engine.peekaboo.tests.GetAddressOfDeviceTests.<init>(GetAddressOfDeviceTests.java:21)
I didn't write the above packages but according to the internal codebase they are the latest stable changes and when I look at the actual file com.company.raft.utils.IonUtil.createJacksonIonMapper:
JoiObjectMapper mapper = new JoiObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
the method setSerializationInclusion is in JoiObjectMapper's superclass' superclass. So why is it unable to find the method?

Android ICS build fails with error 41

I tried to build Android ICS on Ubuntu 10.04 LTS. All was fine, until ubuntu installed next update for Java.
After this, build fails with error 41:
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/java/util/PropertyPermission.java:2: java.util.PropertyPermission is not abstract and does not override abstract method hashCode() in java.security.Permission
public final class PropertyPermission
^
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/java/util/logging/LoggingPermission.java:2: java.util.logging.LoggingPermission is not abstract and does not override abstract method hashCode() in java.security.Permission
public final class LoggingPermission
^
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/javax/net/ssl/SSLPermission.java:2: javax.net.ssl.SSLPermission is not abstract and does not override abstract method hashCode() in java.security.Permission
public final class SSLPermission
^
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/javax/security/auth/AuthPermission.java:2: javax.security.auth.AuthPermission is not abstract and does not override abstract method hashCode() in java.security.Permission
public final class AuthPermission
^
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/javax/security/auth/PrivateCredentialPermission.java:2: javax.security.auth.PrivateCredentialPermission is not abstract and does not override abstract method hashCode() in java.security.Permission
public final class PrivateCredentialPermission
^
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/org/apache/http/impl/conn/tsccm/BasicPoolEntryRef.java:5: warning: [unchecked] unchecked conversion
found : java.lang.ref.ReferenceQueue
required: java.lang.ref.ReferenceQueue<? super org.apache.http.impl.conn.tsccm.BasicPoolEntry>
public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry entry, java.lang.ref.ReferenceQueue<java.lang.Object> queue) { super(null,(java.lang.ref.ReferenceQueue)null); throw new RuntimeException("Stub!"); }
^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
111 errors
6 warnings
make: *** [out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes.jar] Error 41
I searched through net, but found only this tip: http://kimoto.tistory.com/26 and some questions (unanswered) in mailing lists.
Unfortunately, it didn't help for me.
My JAVA_HOME points to /usr/lib/jvm/java-6-sun which is symlink to jdk1.6.0_30.
So looks like I now used latest version of Java.
Ok, resolution was to use open-jdk instead of jdk. It helped to me.

App works perfectly on 1.6, but why am I getting java.lang.VerifyError on Xperia X10 running 1.6?

My app works perfectly on both emulated and real 1.6 devices. However The Sony Xperia X10 series (running 1.6) is crashing with a java.lang.VerifyError. This thread leads me to believe ProGuard optimization could be the culprit, but if that were the case wouldn't the problem exist on every device running 1.6, instead of just the X10?
Here is the stack trace:
java.lang.VerifyError: com.twocell.walkabout.Animator
at com.twocell.walkabout.Main.void onCreate(android.os.Bundle)(SourceFile:197)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2443)
at android.app.ActivityThread.access$2100(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1815)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Here is the code that triggers the error (in a class called 'Animator'):
static void setLayoutAnimation_textFadeIn(ViewGroup vg, Context context)
{
Animation text_fadeIn = AnimationUtils.loadAnimation(context, R.anim.text_fade_in);
LayoutAnimationController controller = new LayoutAnimationController(text_fadeIn, 0.25f);
vg.setLayoutAnimation(controller);
}
which is called from:
LinearLayout HeaderBar_Text = (LinearLayout) findViewById(R.id.HeaderBar_Text);
Animator.setLayoutAnimation_textFadeIn(HeaderBar_Text, this); // this is line 197
and here is text_fade_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1000"
/>
</set>
I don't have access to an X10 so I'm relying on stack traces delivered via ACRA.
EDIT (new info):
Ok, I was able to find an old emulator image of the X10 running 1.6 and re-create the problem. Turns out, it /is/ only crashing on the release (ProGuard) version. Turn off ProGuard and it works perfectly. Why on earth this only affects the X10 and not every single 1.6 device is the question. Here is some new info I've gathered since I have the emulator...
On some of my Activities I'm using overridePendingTransition to change to a fading effect, however this is not supported on 1.6, so I'm using a helper class called VersionHelper:
class VersionHelper
{
static void overrideTransition(Context context)
{
((Activity)context).overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out);
}
}
and it's called from Animator:
static void overrideTransition(Context context)
{
if (Build.VERSION.SDK_INT > 4)
{
VersionHelper.overrideTransition(context);
}
}
This allows 1.6 devices to run the rest of the code without crashing from the unsupported method (Thanks to Mark Murphy for this technique).
Now, the stack trace with extra log data:
07-19 23:42:29.150: ERROR/dalvikvm(705): Could not find method android.app.Activity.overridePendingTransition, referenced from method com.twocell.walkabout.Animator.overrideTransition
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: unable to resolve virtual method 14: Landroid/app/Activity;.overridePendingTransition (II)V
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: rejecting opcode 0x6e at 0x0012
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: rejected Lcom/twocell/walkabout/Animator;.overrideTransition (Landroid/content/Context;)V
07-19 23:42:29.150: WARN/dalvikvm(705): Verifier rejected class Lcom/twocell/walkabout/Animator;
07-19 23:42:29.160: DEBUG/AndroidRuntime(705): Shutting down VM
07-19 23:42:29.160: WARN/dalvikvm(705): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): Uncaught handler: thread main exiting due to uncaught exception
07-19 23:42:29.160: ERROR/AndroidRuntime(705): java.lang.VerifyError: com.twocell.walkabout.Animator
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.twocell.walkabout.Main.onCreate(SourceFile:199)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.access$2100(ActivityThread.java:116)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.os.Handler.dispatchMessage(Handler.java:99)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.os.Looper.loop(Looper.java:123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.main(ActivityThread.java:4203)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at java.lang.reflect.Method.invokeNative(Native Method)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at java.lang.reflect.Method.invoke(Method.java:521)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at dalvik.system.NativeStart.main(Native Method)
So there it is - when I use ProGuard, and only on the X10, it's still seeing overridePendingTransition and crashing. (I confirmed that the X10 /is/ reporting "4" as its API version.)
Finally, my proguard.cfg:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep class com.android.vending.billing.**
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#ACRA specifics
# we need line numbers in our stack traces otherwise they are pretty useless
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
# ACRA needs "annotations" so add this...
-keepattributes *Annotation*
# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
*;
}
# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
*;
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public void addCustomData(java.lang.String,java.lang.String);
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable);
}
-keep class org.acra.ReportField {*;}
Any thoughts?
Edit 2
Using -dontoptimize in ProGuard lets the app run on the X10. I'm sneaking up on a solution.
ProGuard's optimization step will inline methods like VersionHelper#overrideTransition(), which is not what you want, since the method is intended to isolate the dependency on 1.6 (although ProGuard can't know this).
Brute-force solution: switch off all optimizations:
-dontoptimize
Finer-grained: switch off all method inlining (as you've found out):
-optimizations !method/inlining/*
Ideal solution: avoid inlining this particular method and its siblings:
-keepclassmembers,allowobfuscation,allowshrinking somepackage.VersionHelper {
<methods>;
}
Without details, I can't say much about the other issues. You can ask questions on ProGuard's help forum.
Your com.twocell.walkabout.Animator class implementation is referring to some class or method that does not exist on the Xperia X10. It does not have to be limited to something in the static setLayoutAnimation_textFadeIn() method -- it can be anything on that class. Unfortunately, the VerifyError does not say what cannot be found.
You will have to go through your application with a fine-toothed comb and determine what might be missing on the Xperia X10 that exists elsewhere.
but if that were the case wouldn't the problem exist on every device running 1.6, instead of just the X10?
Yes.
The solution was to add -optimizations !method/inlining/unique to proguard.cfg, which according to ProGuard's docs normally "Inlines methods that are only called once". I wish I could say I figured that out without excluding every single optimization then removing them one by one as I built signed releases... but that's exactly what I did.
Edit (new info)
As I continue working I'm discovering that there are other parts of my app that are crashing on the X10, and require other specific optimization exclusions to work properly. I'm also beginning to see a pattern with crash reports from other specific devices that simply should not be happening, and in fact don't happen on my own test devices and emulators.
I am forced to conclude that I cannot trust ProGuard's optimizations at this point. Since the problems only occur on specific devices, I'm more likely to place blame on manufacturer customizations, and not ProGuard. Finding the actual link between the two is beyond my capability.
So my final solution is to use -dontoptimize or risk getting 1-star reviews due to unsolvable problems. Neat. I've never been one to complain about platform fragmentation until now. This particular discovery is a serious disappointment.
Edit 2 (followup)
Since I pushed an update removing the optimization outright, all crashing has stopped. Now I can finally get back to feature development.

Categories

Resources