почему мое приложение выдает исключение финализатора в Android?

#android #database #sqlite

#Android #База данных #sqlite

Вопрос:

у меня есть приложение, в котором постоянно генерируется это исключение…

 04-25 18:47:38.024: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.035: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44dd1e68 on null that has not been deactivated or closed
04-25 18:47:38.035: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.035: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.044: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.064: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e4c048 on null that has not been deactivated or closed
04-25 18:47:38.064: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.064: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.074: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.094: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e35310 on null that has not been deactivated or closed
04-25 18:47:38.094: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.094: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.104: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.104: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e7f738 on null that has not been deactivated or closed
04-25 18:47:38.104: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.104: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.114: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.136: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e04a90 on null that has not been deactivated or closed
04-25 18:47:38.136: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.136: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.155: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.155: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e944f0 on null that has not been deactivated or closed
04-25 18:47:38.155: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.155: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.164: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.184: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e90548 on null that has not been deactivated or closed
04-25 18:47:38.184: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.184: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.194: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.194: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e6b0c8 on null that has not been deactivated or closed
04-25 18:47:38.194: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.194: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.204: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.225: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e4af40 on null that has not been deactivated or closed
04-25 18:47:38.237: INFO/dalvikvm(10290):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.245: INFO/dalvikvm(10290):     at dalvik.system.NativeStart.run(Native Method)
  

я не понимаю, почему это происходит. я закрыл все свои курсоры, а также я закрыл курсоры перед базами данных…
ie c.close() предшествует db.close()

в чем может быть проблема?

заранее благодарю вас.

РЕДАКТИРОВАТЬ: я думаю, что этот класс вызывает исключение, потому что он единственный, кто имеет дело с базами данных

 package com.helios.NauticDates;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class HandleDatabase {

    public void executeSql(String query) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        db.execSQL(query);
        db.close();
    }

    public boolean checkCategory(String name) {
        // TODO Auto-generated method stub
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        String query = "select * from EventCategories where categoryname ='"
                  name   "'";
        Cursor c = db.rawQuery(query, null);
        if (c.getCount() == 0) {
            c.close();
            db.close();
            return true;
        } else {
            c.close();
            db.close();
            return false;
        }
    }

    public String[][] getData(String[] columnnames, String tablename) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        String query = "select ";
        for (int i = 0; i < columnnames.length; i  ) {
            if (i == columnnames.length - 1)
                query  = columnnames[i]   " ";
            else
                query  = columnnames[i]   ",";
        }
        query  = "from "   tablename   " where eventid=128";
        Cursor c = db.rawQuery(query, null);
        String[][] result = new String[c.getColumnCount()][c.getCount()];
        for (int i = 0; i < c.getColumnCount(); i  ) {
            c.moveToFirst();
            for (int j = 0; j < c.getCount(); j  ) {
                result[i][j] = c.getString(c.getColumnIndex(columnnames[i]));
                Log.i("getdata", result[i][j]);
                c.moveToNext();
            }
        }
        c.close();
        db.close();
        return result;
    }

    public boolean checkIfThereIsEvent(String cdate, Date currentdate) {
        Date enddate = (Date) currentdate.clone();
        enddate.setHours(0);
        enddate.setMinutes(0);
        enddate.setSeconds(0);
        String edate = (String) android.text.format.DateFormat.format(
                "yyyy-MM-dd", enddate);

        Log.i("handledatabase", cdate   "-"   edate);
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        String query = "SELECT datetime(startdat, 'unixepoch') AS std, datetime(enddat, 'unixepoch') AS end FROM EventDetails WHERE ((std <= '"
                  cdate
                  "' AND end >= '"
                  cdate
                  "' )||( date(enddat,'unixepoch') = '1970-01-01' AND date(startdat,'unixepoch') = '"
                  edate   "')) LIMIT 1";
        Log.i("thequery", query);
        Cursor c = db.rawQuery(query, null);
        if (c.getCount() > 0) {
            c.close();
            db.close();
            return true;
        }
        {
            c.close();
            db.close();
            return false;
        }
    }

    public boolean checkEventInDatabase(String dateofchange, String eventid) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        String query = "select * from EventDetails where eventid='" eventid "' limit 1";
        Cursor c = db.rawQuery(query, null);
        if(c.getCount()==0){
            c.close();
            db.close();
            return false;
        }
        else{
            query = "select * from EventDetails where eventid='" eventid "'and changed='" dateofchange "' limit 1";
            c= db.rawQuery(query, null);
            if(c.getCount()>0){
                c.close();
                db.close();
                return true;
            }
            else{
                c.close();
                db.close();
                return true;
            }
    }
}

    public boolean checkIfEventChanged(String dateofchange, String eventid) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(
                "/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
                null, SQLiteDatabase.OPEN_READWRITE);
        String query = "select * from EventDetails where eventid='" eventid "'and changed='" dateofchange "' limit 1";
        Cursor c= db.rawQuery(query, null);
        if(c.getCount()>0){
            c.close();
            db.close();
            return false;
        }
        else{
            c.close();
            db.close();
            return true; 
    }
    }
}
  

Комментарии:

1. не могу сказать вам ничего больше, чем то, что говорится в сообщении об ошибке, не видя какого-либо кода.

2. обычно, когда выдается это исключение …?

3. пожалуйста, покажите нам полную ошибку, а не только первые 3 строки…

4. это полная ошибка, эта же ошибка повторяется снова и снова…

5. при каком условии вы получаете это выполнение…

Ответ №1:

Вы пропускаете else ближе к концу checkIfThereIsEvent() .

Если это не устраняет проблему, просто регистрируйте каждый, Cursor который вы открываете самостоятельно с помощью вызова Log , а затем сравните записи журнала, чтобы выяснить, какая Cursor из них является утечкой.

Также:

  • Никогда не проводите пути. Избавьтесь от /data/data/com.helios.NauticDates . Либо используйте SQLiteOpenHelper , либо используйте getDatabasePath() .
  • Нет смысла постоянно открывать и закрывать вашу базу данных таким образом. Пожалуйста, рассмотрите возможность использования SQLiteOpenHelper , поместив эти методы в этот класс и сохранив свои SQLiteOpenHelper дольше (например, время жизни вашей активности или службы или синглтон для всего вашего приложения)

Комментарии:

1. Else там не важно, потому что if содержит возврат, поэтому, когда оператор if имеет значение true, метод никогда не выполняет блок, который должен быть частью else

2. @WarrenFaith: Да, я вроде как предполагал, что все будет в порядке, но я хотел указать на это на всякий случай.

Ответ №2:

Дополнение к CommonsWare:

В вашем checkEventInDatabase() вы переназначаете c переменную, если c.getCount() значение не равно 0, поэтому вы создаете курсор, который вы никогда не закрываете.

И пожалуйста: каждый раз, когда вы вызываете getCount() или getColumnCount() в цикле, бог убивает котенка! (см. getData() )