robospice icon indicating copy to clipboard operation
robospice copied to clipboard

VerifyError on Android 5.0: Rejecting class GsonObjectPersister that attempts to sub-class erroneous class SpringAndroidObjectPersister

Open ajans opened this issue 10 years ago • 10 comments

This error pops into Logcat with Robospice 1.4.14 (commit 5f66030) on Android 5.0 (Nexus 10 and Nexus 7) using SpiceArrayAdapter from com.octo.android.robospice.spicelist.simple and the GsonSpringAndroidSpiceService.

The stacktrace and exact error message is as follows:

E/art(2849): Rejecting class com.octo.android.robospice.persistence.springandroid.json.gson.GsonObjectPersister that attempts to sub-class erroneous class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister in /data/app/de.billiger.android-1/base.apk
D//DefaultRequestRunner.java:219(2849): 14:16:08.282 Thread-1181 An unexpected error occurred when processsing request CachedSpiceRequest [requestCacheKey=https://api.billiger.de/content/2.0/get_category_tree, cacheDuration=86400000, spiceRequest=de.billiger.android.categories.CategoryTreeRequest@31262d71]
D//DefaultRequestRunner.java:219(2849): java.lang.VerifyError: Rejecting class com.octo.android.robospice.persistence.springandroid.json.gson.GsonObjectPersister that attempts to sub-class erroneous class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister (declaration of 'com.octo.android.robospice.persistence.springandroid.json.gson.GsonObjectPersister' appears in /data/app/de.billiger.android-1/base.apk)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.persistence.springandroid.json.gson.GsonObjectPersisterFactory.createInFileObjectPersister(GsonObjectPersisterFactory.java:42)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.persistence.file.InFileObjectPersisterFactory.createObjectPersister(InFileObjectPersisterFactory.java:115)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.persistence.file.InFileObjectPersisterFactory.createObjectPersister(InFileObjectPersisterFactory.java:21)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.persistence.CacheManager.getObjectPersister(CacheManager.java:183)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.persistence.CacheManager.loadDataFromCache(CacheManager.java:68)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.request.DefaultRequestRunner.loadDataFromCache(DefaultRequestRunner.java:262)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.request.DefaultRequestRunner.processRequest(DefaultRequestRunner.java:99)
D//DefaultRequestRunner.java:219(2849):     at com.octo.android.robospice.request.DefaultRequestRunner$1.run(DefaultRequestRunner.java:217)
D//DefaultRequestRunner.java:219(2849):     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
D//DefaultRequestRunner.java:219(2849):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
D//DefaultRequestRunner.java:219(2849):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
D//DefaultRequestRunner.java:219(2849):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
D//DefaultRequestRunner.java:219(2849):     at java.lang.Thread.run(Thread.java:818)
D//DefaultRequestRunner.java:219(2849): Caused by: java.lang.VerifyError: Rejecting class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister because it failed compile-time verification (declaration of 'com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister' appears in /data/app/de.billiger.android-1/base.apk)
D//DefaultRequestRunner.java:219(2849):     ... 13 more

Do you need any more information?

ajans avatar Dec 04 '14 13:12 ajans

this VerifyError seems to be related to this change in the ART-runtime:

https://android.googlesource.com/platform/art/+/1c5eb70%5E!/

ajans avatar Dec 04 '14 14:12 ajans

Hi Arne,

but what is wrong with the super class ? Do you have any way to know it ? Usually such problem are logged at the WARNING level in logcat, prior to the error.

Thx for this bug report, it is quite unexpected though..

Stéphane

2014-12-04 9:13 GMT-05:00 Arne Jans [email protected]:

this VerifyError seems to be related to this change in the ART-runtime:

https://android.googlesource.com/platform/art/+/1c5eb70%5E!/

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/robospice/issues/387#issuecomment-65636941 .

stephanenicolas avatar Dec 04 '14 14:12 stephanenicolas

It may or may not be related to this Demo-Project with workaround for a similar VerifyError, albeit not referring to sub-classing:

https://github.com/aectann/android-verify-error-example

I will try the given workaround with the class GsonObjectPersisterFactory line 42 to see if it helps.

Logcat shows only one warning twice, which might be related:

W/art(7171): Attempt to remove local handle scope entry from IRT, ignoring

I will let you know what comes out of this.

ajans avatar Dec 04 '14 15:12 ajans

The presumed workaround didn't change anything, the class GsonObjectPersister still gets rejected. As our latest app-release works with our customized version of robospice-1.4.2-SNAPSHOT, I think I might have to git bisect the robospice-history to determine which commit introduced the incompatible change.

But right before that, I have to check our toolchain, maybe our recently introduced DexGuard-tool introduced some sort of incompatibility, as we use its shrinking-capabilities it for our debugging-builds, too.

ajans avatar Dec 05 '14 08:12 ajans

Disabling DexGuard doesn't help anything. I can confirm that the problem doesn't exist with robospice-1.4.2-SNAPSHOT for debug- and release-builds (release is obfuscated with Proguard/DexGuard).

My previous logcat-excerpt did filter too much, it was filtering by the application-name. If I do not filter anything in logcat, I can see the following output from dex2oat:

I/dex2oat(29475): /system/bin/dex2oat --zip-fd=6 --zip-location=/data/app/de.billiger.android-1/base.apk --oat-fd=7 --oat-location=/data/dalvik-cache/arm/data@[email protected]@[email protected] --instruction-set=arm --instruction-set-features=default --runtime-arg -Xms64m --runtime-arg -Xmx512m
I/dex2oat(29475): Verification error in java.lang.Object com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister.readCacheDataFromFile(java.io.File)
I/dex2oat(29475): java.lang.Object com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister.readCacheDataFromFile(java.io.File) failed to verify: expected to be within a catch-all for an instruction where a monitor is heldAndroidObjectPersister.readCacheDataFromFile(java.io.File): [0xA]
E/dex2oat(29475): Verification failed on class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister in /data/app/de.billiger.android-1/base.apk because: Verifier rejected class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister due to bad method java.lang.Object com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister.readCacheDataFromFile(java.io.File)
E/dex2oat(29475): Rejecting class com.octo.android.robospice.persistence.springandroid.json.gson.GsonObjectPersister that attempts to sub-class erroneous class com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister in /data/app/de.billiger.android-1/base.apk

Does that information help you in any way? I didn't modify anything in the Persister-classes.

Did you have any similar error messages related to ART and dex2oat?

ajans avatar Dec 05 '14 09:12 ajans

This issue in the Android tracker seems to be related, too: https://code.google.com/p/android/issues/detail?id=80961

It is maybe an issue with testcoverage being enabled during build and thus causing the jacoco-tool to not update the exception-tables correctly, thus the android-runtime discovers this error and complains about it.

How could I disable the testcoverage for a build? In Gradle, the corresponding directive is called "testCoverageEnabled".

As one commenter pointed out: Confirmed Removing testCoverageEnabled true from the Gradle file prevents the VerifyError.

ajans avatar Dec 05 '14 10:12 ajans

After revisiting this issue and some experimenting, I dug into the specific error "SpringAndroidObjectPersister.readCacheDataFromFile(java.io.File) failed to verify: expected to be within a catch-all for an instruction where a monitor is held".

The mentioned method has a weird try-catch-logic as it catches FileNotFoundException, which is never thrown here, instead of IOException, and also it re-catches CacheLoadingException to give it precedence relative to the generic Exception-catch.

I simplified this try-catch-construct to only catch IOException for FileUtils.readFileToString and re-throw it wrapped in CacheLoadingException. If the cachefile is empty, the CacheLoadingException is also thrown as usual.

The fix is a change made against the latest release-tag robospice-parent-1.4.14 in the extension robospice-spring-android (as I had some trouble building on current master). Is it okay for you to get the Pull Request with this base? Or do you want the PR as a fix-branch to be rebased against master?

ajans avatar Dec 17 '14 10:12 ajans

I can confirm the SpringAndroidObjectPersister delivers cache-results on Android 5.0 with ART-runtime with this patch again.

ajans avatar Dec 17 '14 10:12 ajans

Thx Arne for the PR, we will look into it shortly now. Sorry for the delay, I had real xmas holidays, even a bit extended due to an injury at the right hand. But we are back ;)

stephanenicolas avatar Jan 17 '15 12:01 stephanenicolas

Any updates on this one?

deinlandel avatar Apr 24 '15 11:04 deinlandel