agrosner / DBFlow

A blazing fast, powerful, and very simple ORM android database library that writes database code for you.
MIT License
4.87k stars 598 forks source link

Attempt to invoke virtual method '....RetrievalAdapter.getModelClass()' on a null object reference #1730

Open jchristof opened 2 years ago

jchristof commented 2 years ago

DBFlow Version: 4.2.4

Bug or Feature Request: Attempt to invoke virtual method '....RetrievalAdapter.getModelClass()' on a null object reference

Description: I'm getting the exception occasionally in production. Not sure why this fails only occasionally. Anyone have an idea?

Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'java.lang.Class com.raizlabs.android.dbflow.structure.RetrievalAdapter.getModelClass()' on a null object reference

com.raizlabs.android.dbflow.sql.saveable.ModelSaver.getWritableDatabase (ModelSaver.java:169)
com.raizlabs.android.dbflow.sql.saveable.ModelSaver.save (ModelSaver.java:29)
com.raizlabs.android.dbflow.structure.ModelAdapter.save (ModelAdapter.java:186)
com.raizlabs.android.dbflow.structure.BaseModel.save (BaseModel.java:62)
jschools commented 7 months ago

I am also getting this error occasionally. I think it is a race condition in ModelAdapter.getModelSaver(). The ModelAdapter lazily initializes an instance of ModelSaver without synchronization here: https://github.com/agrosner/DBFlow/blob/0e06ea867c09db100a040314ca5127911afb16f9/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/ModelAdapter.java#L429 If multiple threads call getModelSaver() concurrently, it is possible for one thread to get (and attempt to use) the modelSaver instance before setModelAdapter(this) has been called on it, leading to the NPE.

This seems to have been (kind of) fixed in 5.0.0-alpha2. It could result in multiple instances of ModelSaver being used, which would solve this crash but introduce the possibility of synchronization errors, since ModelSaver has several @Synchronized functions: https://github.com/agrosner/DBFlow/blob/8c86eaa78f052be9d1990f637c8f50da287f7095/lib/src/main/kotlin/com/dbflow5/adapter/ModelAdapter.kt#L178 It is not trivial to upgrade to the new library, and it is also risky to upgrade to a new major "dot zero alpha" version.

As a workaround, you could call .getModelSaver() on each ModelAdapter immediately after initializing DbFlow, as long as you can ensure no other threads are calling save() while this is happening.

loquitowen commented 7 months ago

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。