简体   繁体   中英

StackOverflowError when using a query in a recursive method

In local database I have records with information about dirs and files (file system tree). For example, table "Dir" has attributes: record_id (autoincr.), dir_id , dirname , parentDir_id . I need to create a files and dirs tree from database:

Dir_1
|
 -----Dir_1.1
 -----Dir_1.2
 -----File_1.1
Dir_2
|
 -----Dir_2.1
 -----Dir_2.2
 -----File_2.1
 -----File_2.2
Dir_3
File_1
File_2

So, I use recursive method. My function:

 /**
 * Append new childs for target dir
 * @param targetObject directory
 */
public void addChilds(@Nullable SimpleSyncDirModel targetObject){
    //no target - main parent dir.
    if (targetObject == null){
        //get childs for this target object (main dir without parent)
        ArrayList<Object> foundedChilds = ThisApp.getDBhelper().getSharedSimpleObjects(this.dir_id);
        //step by step (childs). recursive mecthod.
        for (Object thisChild : foundedChilds){
            if (thisChild instanceof SimpleSyncDirModel){
                addNewChildDir((SimpleSyncDirModel) thisChild);
                //find and add childs for current child
                addChilds((SimpleSyncDirModel) thisChild);
            }else if (thisChild instanceof SimpleSyncFileModel){
                addNewChildFile((SimpleSyncFileModel) thisChild);
            }
        }
    }else{
        //get childs for this target object (not main, has parent)
        ArrayList<Object> foundedChilds = ThisApp.getDBhelper().getSharedSimpleObjects(targetObject.dir_id);
        //iterate, find and append childs (recursive)
        for (Object thisChild : foundedChilds){
            if (thisChild instanceof SimpleSyncDirModel){
                targetObject.addNewChildDir((SimpleSyncDirModel) thisChild);
                //recursive
                addChilds((SimpleSyncDirModel) thisChild);
            }else if (thisChild instanceof SimpleSyncFileModel){
                targetObject.addNewChildFile((SimpleSyncFileModel) thisChild);
            }
        }

    }
}

As you see, I use function

ThisApp.getDBhelper().getSharedSimpleObjects(targetObject.dir_id);

for searching childs of target dir. targetObject.dir_id - parent_id for "SELECT".

My search childs function:

 /**
 * Get childs with parent_id == 0 (without parent) or not (with parent)
 * @param parendDir_id ID of dir, for what we search childs
 * @return list of childs like {@link SimpleSyncDirModel}
 * and {@link ru.rsit.megashare.models.global.SimpleSyncFileModel}
 */
public ArrayList<Object> getSharedSimpleObjects(String parendDir_id){

    ArrayList<Object> result = new ArrayList<>();

    //looking child dirs
    String[] columns_ = new String[]{
            "dir_id", "dirnameWithPath"
    };
    Cursor db_cursor = megashare_db.query(
            "SharedDir", columns_,
            "(parentDir_id = ?)",
            new String[] { parendDir_id },
            null, null, null);
    if (db_cursor.getCount() > 0) {
        db_cursor.moveToFirst();
        while (db_cursor.getPosition() != db_cursor.getCount()) {
            SimpleSyncDirModel simpleSyncDirModel = new SimpleSyncDirModel();
            simpleSyncDirModel.dir_id =
                    Integer.toString(db_cursor.getInt(db_cursor.getColumnIndex("dir_id")));
            simpleSyncDirModel.dirnameWithPath =
                    db_cursor.getString(db_cursor.getColumnIndex("dirnameWithPath"));
            result.add(simpleSyncDirModel);
            db_cursor.moveToNext();
        }
    }
    db_cursor.close();

    //looking child files
    columns_ = new String[]{
            "file_id", "filenameWithPath"
    };
    db_cursor = megashare_db.query(
            "SharedFile", columns_,
            "(parentDir_id = ?)",
            new String[] { parendDir_id },
            null, null, null);
    if (db_cursor.getCount() > 0) {
        db_cursor.moveToFirst();
        while (db_cursor.getPosition() != db_cursor.getCount()) {
            SimpleSyncFileModel simpleSyncFileModel = new SimpleSyncFileModel();
            simpleSyncFileModel.file_id =
                    Integer.toString(db_cursor.getInt(db_cursor.getColumnIndex("file_id")));
            simpleSyncFileModel.filenameWithPath =
                    db_cursor.getString(db_cursor.getColumnIndex("filenameWithPath"));
            result.add(simpleSyncFileModel);
            db_cursor.moveToNext();
        }
    }
    db_cursor.close();

    return result;
}

When I run my app and try to create file system tree, I always see java.lang.StackOverflowError :

FATAL EXCEPTION: Thread-23110
 java.lang.StackOverflowError
     at java.lang.ref.WeakReference.<init>(WeakReference.java:108)
     at java.util.WeakHashMap$Entry.<init>(WeakHashMap.java:71)
     at java.util.WeakHashMap.put(WeakHashMap.java:611)
     at android.database.sqlite.SQLiteConnectionPool.finishAcquireConnectionLocked(SQLiteConnectionPool.java:980)
     at android.database.sqlite.SQLiteConnectionPool.tryAcquirePrimaryConnectionLocked(SQLiteConnectionPool.java:916)
     at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:682)
     at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:400)
     at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:905)
     at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:586)
     at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
     at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
     at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
     at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1436)
     at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1283)
     at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1154)
     at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1322)
     at ru.rsit.megashare.managers.DBHelper.getSharedSimpleObjects(DBHelper.java:582)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:64)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
     at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
    at

Error is here: Cursor db_cursor = megashare_db.query

Why I have this error? Of course I close always cursor. What I need to do for resolve this problem?

The reason of error is mistake in code, where I try to find in database target dir for check: is this directory has no parent. So, my app duplicates some dirs, if I remove child object. That's why recursion going to cycle.

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