0

Sometimes I'm receiving crash reports from google caused by random NullPointerExceptions (see above). I tried to reproduce those errors but I'm not able to catch them.

Examples of NPE I get :

Caused by: java.lang.NullPointerException
at com.gamequiz.databasemanager.CategoryManager.getAllCategories(CategoryManager.java:28)

Caused by: java.lang.NullPointerException
at com.gamequiz.databasemanager.QuestionManager.getQuestionsFromLevel(QuestionManager.java:30)
at com.gamequiz.databasemanager.QuestionManager.getNumberOfQuestionAnsweredFromLevel(QuestionManager.java:148)


I though that my dbHelper variable is null sometimes but I can't figure out why.

Since I don't know how to resolve that, I post the all steps of my code :

First of all I initialize all the managers in the LaunchActivity :

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_launch);

        initializeAllManagers();

       //some stuff

}

public void initializeAllManagers(){
        InitializeAllManagers.init(getApplicationContext());
    }

In my InitializeAllManagers class, I set all the managers I need for the lifecycle of the app :

public class InitializeAllManagers {

    public static void init(Context context){
        DatabaseManager.init(context);
        CategoryManager.init(DatabaseManager.getInstance().getHelper());
        //and others initializations
    }
}

DatabaseManager class (initialization of the dbManager and dbHelper) :

public class DatabaseManager {

    private static DatabaseManager instance;
    private DatabaseHelper helper;

    public static void init(Context ctx) {
        if (instance==null) {
            instance = new DatabaseManager(ctx);
        }
    }

    public static DatabaseManager getInstance() {
        return instance;
    }

    private DatabaseManager(Context ctx) {
        helper = new DatabaseHelper(ctx);
    }

    public DatabaseHelper getHelper() {
        return helper;
    }
}

Finally there is an example of one manager :

public class CategoryManager {

    private static DatabaseHelper dbHelper;

    public static void init(DatabaseHelper dbHelperInstance) {
        dbHelper = dbHelperInstance;
    }

    public static ArrayList <Category> getAllCategories(){
            ArrayList <Category> cList = null;
            try {
                cList = (ArrayList<Category>) dbHelper.getCategoryDao().queryForAll();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return cList;
    }
}

So I suspect that my dbHelper variable is null sometimes. Does anyone have an idea about how I can solve this issue ?

EDIT :

NPE mainly refers to this lines :

cList = (ArrayList<Category>) dbHelper.getCategoryDao().queryForAll(); 
Dao <Question, Long> questionDao = dbHelper.getQuestionDao();

That's why I suspect that dbHelper is null sometimes, and apparently crashes occurs when the app is sleeping for a moment (see feedback above).


Feedback of one user :

So, mainly if I leave the app without exiting it, the app will often crash when I try to go back to it. Sometimes I just get sent back to the menu, but mostly just all the way out of the app and I have to restart it to continue.

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • Any idea what specific line numbers corresponds to the NPEs? – Gray Apr 18 '13 at 00:35
  • The `dbHelper` can be `null` or the dao returned by `getCategoryDao()` could be `null`. Can you show that code? – Gray Apr 18 '13 at 00:36
  • Is there no way that the helper could be assigned to `null`? Can that be changed to be `final`? – Gray Apr 18 '13 at 00:39
  • @Gray Question edited. Do you think that change the `dbHelper` to be `final` in the `DatabaseManager` class could resolve that ? I'm not an expert about the lifecycle of an activity. If the app is sleeping for a moment, do I have to force it to reinitialize the managers when the user re-opened it (which seems odd)? – Alexis C. Apr 18 '13 at 08:10
  • No @ZouZou, you should not have to do that. I suspect something is not being initialized right, maybe as part of the lifecycle but start/destroy are what ORMLite uses internally so you should be good. – Gray Apr 18 '13 at 13:26
  • @Gray I have no idea about how I can fix that. [This thread](http://stackoverflow.com/questions/14699879/nullpointerexception-crash-reports-using-static-databasehelper) related the same problem I think. Btw, you did an awesome job about this library :) – Alexis C. Apr 18 '13 at 17:51

1 Answers1

0

I suspect that this happens when the app is minimized for a while and then get re-opened. Android can and will remove Objects from the heap if it feels like it needs the memory. Especially static variables can be removed. Check static variables for null before you access them.

For example in your DatabaseManager class, create the instance in the getInstance() method instead of in init().

public static DatabaseManager getInstance() {
    if(instance == null) instance = new DatabaseManager();
    return instance;
}

Edit:
Please note that my reasoning in this answer is wrong. Please read all the comments for clarification.

SimonSays
  • 10,867
  • 7
  • 44
  • 59
  • With respect, absolute nonsense. Android only removes objects if they are garbage collected. It doesn't "feel like removing" anything. It might destroy your Activities, as documented and controlled through the Application life cycle. The Activity will be recreated when your app is brought back to the foreground and of course, any variables it declares will be re-initalised which is the purpose of onPause() and onResume() with the many ways of dealing with saving and restoring state. "Especially static variables can be removed". Huh? Are you talking about singletons? Application class fields? – Simon Apr 17 '13 at 17:29
  • I mean every static variable, that includes singletons (not constantes of course). When Android needs memory it can choose to remove stuff from the heap, it could for example remove a ClassLoader instance. If this is the ClassLoader that loaded the Class which contains your static variable, this one will be removed too. The Activity might not be affected by this, because it was loaded by another ClassLoader. So, the Activity is still here, but your static variable in another class might not be. I had a similar problem with random NPE and this fixed it. – SimonSays Apr 17 '13 at 18:05
  • Again, no it doesn't. There are only 3 ways for anything to be removed from the heap. 1. An object whose scope is an enclosing Activity, and that Activity gets destroyed. 2. A heap object with zero reference counts. 3. The application is destroyed. Nothing that is still in scope is ever removed. If it were, there would be chaos in Android land. It is entirely determinable when a heap object is collected. – Simon Apr 17 '13 at 19:16
  • After research, it seems that you are right with the point that static variables aren't removed as long as the process is alive. The NPE problem is caused when Android kills the process and tries to restore the last state when the app gets re-opened. If you initialize your static variables in the SpashScreen for example, they will be null in this case. So the above fix, even though my reasoning was wrong, will still resolve the problem. – SimonSays Apr 17 '13 at 20:00
  • Here is an old discusion about the same topic http://stackoverflow.com/questions/5105097/static-references-are-cleared-does-android-unload-classes-at-runtime-if-unused – SimonSays Apr 17 '13 at 20:01