Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObjectInputStream readObject causes RoundingMode.ordinal NullPointerException

Tags:

java

android

EDIT: it seems to be a problem related to Android Pie (api 28). Seems to work on previous versions (tested on 27, 26, 25).


I'm working at this Android code for a very long time, and I noticed that lately when I'm saving data on the disk, I receive this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.math.RoundingMode.ordinal()' on a null object reference

This is how I write data to disk

private void SaveDataToDisk() {
    try {
        FileOutputStream fos = this.weakActivity.get().openFileOutput(this.FILENAME, Context.MODE_PRIVATE);
        if (fos != null) {
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(this.datastore);
            os.close();
            fos.close();
        }
    } catch (Exception ex) {
            ErrorManager.TrapThrow(ex, this.weakActivity.get());
    }
}

this.datastore is a complex object composed of multiple other object (a very large number).

This is how I read data back when needed

private void LoadDataFromDisk() {
    try {
        if (this.weakActivity.get().getFileStreamPath(this.FILENAME).exists()) {
            FileInputStream fis = this.weakActivity.get().openFileInput(this.FILENAME);
            BufferedInputStream bis = new BufferedInputStream(fis);
            ObjectInputStream is = new ObjectInputStream(bis);
            try {
                this.datastore = (DataStore) is.readObject();
            } catch (Exception ex) {
                this.datastore = new DataStore();
            }
            is.close();
            fis.close();
        }
    } catch (Exception ex) {
        ErrorManager.TrapThrow(ex, this.weakActivity.get());
    }
}

Imagine to have a fresh install of the app. The first time LoadDataFromDisk does nothing. Later in time the app writes something on the disk. When the app call LoadDataFromDisk again, it reads correctly. Then, for example, the app is relaunched: when LoadDataFromDisk is reached, and specifically

this.datastore = (DataStore) is.readObject();

I receive the error above, and falls back to a new DataStore object, in order to keep the app working.

Why not always? The data seems corrupted after has been read. I can reproduce on AVD and on my phone.

Any help appreciated

like image 416
Valerio Avatar asked Nov 29 '18 14:11

Valerio


1 Answers

We found that this was caused by a custom DataFormatter object (within a containing, serialized object) that relies on a java.text.DecimalFormat. When we went to deserialize the object (sometimes but not always, but apparently dependent on how many times the containing object had been passed among Activity extras), the entire Extras collection containing the serialized container was invalid, and crashed the app with the RoundingMode.ordinal() NPE.

Apparently the DecimalFormat class no longer plays well with serialization in Android 9/Pie, because in our case it was as simple as marking the containing, Serializable object's instance of DataFormatter as transient and the problem vanished.

Sorry not to have a better dissection of the issue ready, but this solved our problem with this error.

like image 106
Echoloc8 Avatar answered Nov 03 '22 12:11

Echoloc8