为什么我的应用程序在android中抛出终结器异常?

时间:2011-04-25 12:47:33

标签: android database 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)

我不明白为什么会这样。我关闭了所有游标,并且我在数据库之前关闭了游标...... 即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; 
    }
    }
}

2 个答案:

答案 0 :(得分:2)

else结束时您遗漏了checkIfThereIsEvent()

如果没有清除它,只需通过调用Cursor记录您自己打开的每个Log,然后比较日志条目以确定哪个是Cursor被泄露了。

此外:

  • 永远不要硬连线。摆脱/data/data/com.helios.NauticDates。使用SQLiteOpenHelper或使用getDatabasePath()
  • 以这种方式连续打开和关闭数据库没有任何价值。请考虑使用SQLiteOpenHelper,将这些方法放在该类上,并保持SQLiteOpenHelper更长时间(例如,您的活动或服务的生命周期,或整个应用的单身人士)

答案 1 :(得分:2)

CommonsWare的补充:

checkEventInDatabase()中重新分配c变量,如果c.getCount()不为0,那么您可以创建一个永不关闭的光标。

请注意:每当你在一个循环中呼叫getCount()getColumnCount()时,上帝会杀死一只小猫! (见getData()