realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.47k stars 1.75k forks source link

0.88.2 gradle plugin causes io.realm.RealmConfiguration not found? #2514

Closed Qubitium closed 8 years ago

Qubitium commented 8 years ago

Previous working state: 1) Realm 2016-2-18 snapshot directly included as a library 2) Android Studio 2.1 Preview 3 3) Build Tools 23.0.2 4) Not using realm gradle plugin 5) Using Dexguard with official proguard config from realm

Broken state: 1) Official 0.88.2 release from Gradle/jcenter 2) Android Studio 2.1 Preview 3 3) Build Tools 23.0.2 4) Using realm Gradle plugin 5) Using Dexguard with official proguard config from realm

With the offical 0.88.2 and plugin, we are getting this on generated debug apk

LOG: I/art: Rejecting re-init on previously-failed class java.lang.Class<io.realm.RealmConfiguration>

java
java.lang.NoClassDefFoundError: io.realm.RealmConfiguration
at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:359)
at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:322)

Our first assumption was dexguard removing the files but we have checked the unused mapping the realmConfig is not stripped and have added additional

-keep class io.realm.RealmConfiguration { *; }

config with no use. Any help would be appreciate. Right now we have no clue at the cause.

emanuelez commented 8 years ago

I don't think I've seen this one before. Did you try inspecting the apk with a tool suck as classyshark (http://www.classyshark.com) to check that everything looks ok? Also, the first line of your log suggests that there was an error occurring at an earlier stage. Maybe that could help to shed some light on the issue.

Qubitium commented 8 years ago

@emanuelez I have emailed ClassyShark screen capture of said apk to help@realm.io. The RealmConfiguration class is retained as part of the apk dex but for some reason, unloadable in real device.

1) Is the Realm gradle plugin doing dex manipulation? 2) Have you guys tested the plugin with commercial dexguard (not the proguard version)?

beeender commented 8 years ago

1) Is the Realm gradle plugin doing dex manipulation?

No, Realm only does bytecode manipulation before dex manipulation.

2) Have you guys tested the plugin with commercial dexguard (not the proguard version)?

No... I just took a look of their website, it seems they don't have a trial version?

Rejecting re-init on previously-failed class java.lang.Class<io.realm.RealmConfiguration> we used to have a similar warning before, https://github.com/realm/realm-java/issues/1963 . That one is caused by absence of RxJava . Can you please check the log before? Any other related log to init RealmConfiguration class? Although i don't think it will solve the problem, would you please try to add a dummy RxObservable as it is described here https://realm.io/docs/java/latest/#jackson-databind if you are not using RxJava.

emanuelez commented 8 years ago

Also, have you managed to find the first failure?

Qubitium commented 8 years ago

@beeender Tried both the dummy rx.Observerable file and actually inserting the real rxJava dependency in gradle and both yielded the same original RealmConfig error. I also double checked each apk build and all the rx classes are preserved in final dex.

@emanuelez I don't see any prior/"first" error logged anywhere.

zaki50 commented 8 years ago

@diegomontoya are you using multidex?

Qubitium commented 8 years ago

@zaki50 multidex is disabled. dexguard/proguard optimization and obfuscation are disabled but dexguard/proguard shrinking is enabled so the unused classes/methods are stripped to avoid the 65k limit without multidex.

beeender commented 8 years ago

https://secure.helpscout.net/conversation/185293573/3509/?folderId=366141 screenshot mentioned in https://github.com/realm/realm-java/issues/2514#issuecomment-201106510

kuno commented 8 years ago

I dont know if my problem is related to this.

But after I enabled dexguard in my debug build, the application crashed right after launch.

I just using the default realm configuration which ship with Dexguard itself.

Declare: I am on relam-java 0.88.2, and using it as a gradle plugin.


Process: xxx.xxx.xxx PID: 3781
 java.lang.ExceptionInInitializerError: RealmTransformer doesn't seem to be applied. Please update the project configuration to use the Realm Gradle plugin. See https://realm.io/news/android-installation-change/
at io.realm.RealmConfiguration.<clinit>(RealmConfiguration.java:71)
at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:359)
at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:339)
Qubitium commented 8 years ago

Is it normal for Realm bytecode Transformer "Modifying" bytecodes for classes that has no relationship to it? Or is the log label of "Modifying" class mis-labeled?

Below is a partial sample gradle compile output with --info flag set for the Realm transformer run.

   Modifying class com.bumptech.glide.RequestManager$RequestManagerConnectivityListener
    Behavior: RequestManager$RequestManagerConnectivityListener
      Field being accessed: com.bumptech.glide.RequestManager$RequestManagerConnectivityListener.requestTracker
    Behavior: onConnectivityChanged
      Field being accessed: com.bumptech.glide.RequestManager$RequestManagerConnectivityListener.requestTracker
  Modifying class com.bumptech.glide.load.model.ModelCache$1
    Behavior: ModelCache$1
      Field being accessed: com.bumptech.glide.load.model.ModelCache$1.this$0
    Behavior: onItemEvicted
    Behavior: onItemEvicted

Also. I have confirmed that the realm transformation is happening before dexguard processing, which is what we want.

What is more interesting is the warning logs from dexguard run after realm transform completion:

Warning: class [folders/1/1/realm/okio/ForwardingSink.class] unexpectedly contains class [okio.ForwardingSink]
Note: duplicate definition of program class [okio.ForwardingSink]
Warning: class [folders/1/1/realm/okio/BufferedSource.class] unexpectedly contains class [okio.BufferedSource]
Note: duplicate definition of program class [okio.BufferedSource]
Warning: class [folders/1/1/realm/okio/ForwardingTimeout.class] unexpectedly contains class [okio.ForwardingTimeout]
Note: duplicate definition of program class [okio.ForwardingTimeout]
Warning: class [folders/1/1/realm/okio/Okio$3.class] unexpectedly contains class [okio.Okio$3]
Note: duplicate definition of program class [okio.Okio$3]
Warning: class [folders/1/1/realm/okio/Base64.class] unexpectedly contains class [okio.Base64]
Note: duplicate definition of program class [okio.Base64]

"folders/1/1/realm" is the path of the "Build/intermediates/transforms/RealmTransformer" location storing the results of the Realm transform plugin.

kuno commented 8 years ago

@danielgomezrico

Same thing happened to me

dalinaum commented 8 years ago

@kuno's I think your problem is not related to this issue. RealmTransformer doesn't seem to be applied to your application. Did you get Modifying class log like @diegomontoya already reported?

Qubitium commented 8 years ago

Previous notes was under dexguard 7.1.16.

With new dexguard 7.1.18 + 0.88.2: The error has now changed:

Process: xxx, PID: 18025
 java.lang.ExceptionInInitializerError: RealmTransformer doesn't seem to be applied. Please update the project configuration to use the Realm Gradle plugin. See https://realm.io/news/android-installation-change/
 at io.realm.RealmConfiguration.<clinit>(RealmConfiguration.java:71)
at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:359)
at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:322)

The realm transform process was completed.

Realm Transform time: 2931 milliseconds

Here is the Dexguard output part which might explain the the above error.

Note: duplicate definition of program class [io.realm.xxxRealmProxyInterface]
Note: duplicate definition of program class [io.realm.xxxMediator]
Note: duplicate definition of program class [io.realm.xxxProxy]
[ repeats for all for all my custom classes that extends RealmObject ]

Dexguard taking the original (non-transformed) byte class file in it's conflict resolution? If dexguard is taking the transformed class files, the isTransformed method should now return true. Something is not right.

Now my errors aligns with @kuno provided he is also using dexguard 7.1.18 with Realm 0.88.2.

kuno commented 8 years ago

@diegomontoya

yeah, I am on dexguard 7.* but dont know the exact version.

dalinaum commented 8 years ago

Could you post your build.gradle file? Does DexGuard use its own Gradle plugin instead of using Transformer API?

@kuno Sorry for my wrong assumption.

beeender commented 8 years ago

Requested a trial version of dexguard on their website to reproduce this. No response yet.

Qubitium commented 8 years ago

I have emailed guardsquare support to accelerate this process. Their support has been pretty responsive so far.

kuno commented 8 years ago

@dalinaum

no, you are right. I am new to realm, and really dont know much about Transformer.

kuno commented 8 years ago

@dalinaum

In my case I just using the default dexguard configuration that ship with dexguard.jar file.

This is the snippet of my build.gradle

 buildTypes {
        debug {
            proguardFile getDefaultDexGuardFile('dexguard-debug.pro')
        }
}

if you prefer, I can post the configuration here. (if not violate their licence)

kuno commented 8 years ago

any progress here ?

beeender commented 8 years ago

I got a response from DexGuard which redirected my request to another person. They said they would come back to me soon, but still no response yet.

Qubitium commented 8 years ago

@beeender @kuno I got response saying they tested a realm.io 0.88.2 code sample with dexguard 7.1.18 and did not get the same run-time error and needs a reproducible project. Will cook up a test for them later today.

beeender commented 8 years ago

@diegomontoya Great, thanks a lot!

RobertoArtiles commented 8 years ago

It seems like it's indeed DexGuard + Realm 0.88.2 issue. I have exactly the same issue, and we use DexGuard too.

cmelchior commented 8 years ago

Apparently DexGuard is aware of the issue and are working on a fix.

kuno commented 8 years ago

@cmelchior Thanks a lot

kuno commented 8 years ago

Any progress here or on the Dexguard side ?

kuno commented 8 years ago

I've tryt the latest v0.89.0, the problem still there.

beeender commented 8 years ago

@diegomontoya Sorry to trouble you, but did you get any response from DexGuard?

netomi commented 8 years ago

DexGuard developer here: sorry for the delay, but we have improved support for Realm plugin which will be available in next release (7.1.26) available end of this week.

cmelchior commented 8 years ago

Thank you @netomi

Qubitium commented 8 years ago

Just tried 7.1.26 dexguard and confirmed this compat bug with 0.90.1 realm has been fixed.