简体   繁体   中英

infinite loop of Background sticky concurrent mark sweep GC sqlite database

I use an SQLite database in an application, I was trying to add a function that gets some data from the database in a form of a hashmap

 public HashMap<Integer, ArrayList<OrderCustomer>> getOrderCustomers (){
        SQLiteDatabase db = getReadableDatabase();
        String query = "SELECT * FROM " + TABLE_ORDER_CUSTOMER + " ;";
        Cursor cursor = db.rawQuery(query,null);
        cursor.moveToFirst();
        HashMap<Integer, ArrayList<OrderCustomer>> result = new HashMap<>();

        while (!cursor.isAfterLast()){
            int fkOrder = cursor.getInt(cursor.getColumnIndex(OC_FK_ORDER));
            int fkCustomer = cursor.getInt(cursor.getColumnIndex(OC_FK_CUSTOMER));
            double cost = cursor.getDouble(cursor.getColumnIndex(OC_COST));

            OrderCustomer orderCustomer = new OrderCustomer(fkOrder, fkCustomer);
            orderCustomer.setCost(cost);

            ArrayList<OrderCustomer> orderCustomers = new ArrayList<>();

            if(result.containsKey(fkOrder)){
                orderCustomers = result.get(fkOrder);
                result.remove(fkOrder);
            }
            orderCustomers.add(orderCustomer);
            result.put(fkOrder, orderCustomers);
    }
        db.close();
        cursor.close();

        return result;
}

but since I added this function the app gives me an infinite loop of the following:

Background sticky concurrent mark sweep GC freed 133964(3MB) AllocSpace objects, 0(0B) LOS objects, 7% free, 29MB/31MB, paused 34.098ms total 149.711ms

and does not start, and sometimes it crashes with OutOfMemoryError pointing to that function. What's wrong in the function that causes that error?. PS: the app works fine once after the first installation, this may help. Please ask if you any more info.

Your issue is that you are never moving past the first row so the cursor will never be after the last row and hence the infinite loop. This could be fixed by adding cursor.moveToNext(); before the next iteration of the loop.

However, I'd suggest using the simpler

while(cursor.moveToNext) {
    ....... 
}

Instead of using (see comment for fix)

cursor.moveToFirst();
while (!cursor.isAfterLast()){

    cursor.moveToNext(); // <<<<<<<<<< what was omitted
}
  • The above would result in a failure if there were no rows extracted as the moveToFirst isn't checked to see if it was successful.

As such I'd suggest changing you code to be :-

public HashMap<Integer, ArrayList<OrderCustomer>> getOrderCustomers (){
    SQLiteDatabase db = getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_ORDER_CUSTOMER + " ;";
    Cursor cursor = db.rawQuery(query,null);
    HashMap<Integer, ArrayList<OrderCustomer>> result = new HashMap<>();

    while (cursor.moveToNext()){
        int fkOrder = cursor.getInt(cursor.getColumnIndex(OC_FK_ORDER));
        int fkCustomer = cursor.getInt(cursor.getColumnIndex(OC_FK_CUSTOMER));
        double cost = cursor.getDouble(cursor.getColumnIndex(OC_COST));

        OrderCustomer orderCustomer = new OrderCustomer(fkOrder, fkCustomer);
        orderCustomer.setCost(cost);

        ArrayList<OrderCustomer> orderCustomers = new ArrayList<>();

        if(result.containsKey(fkOrder)){
            orderCustomers = result.get(fkOrder);
            result.remove(fkOrder);
        }
        orderCustomers.add(orderCustomer);
        result.put(fkOrder, orderCustomers);
    }     
    cursor.close();
    db.close();
    return result;
}
  • Notes
    • getReadableDatabase will in most situations get a writable database
    • cursor.moveToFirst() has been removed (moveToNext will move to the first row when the cursor is at the position of before the first row (ie -1)).
    • The cursor should be closed before the database is closed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM