Skip to content

Commit 7eb1d97

Browse files
author
Chris Brody
committed
Fix leak in SQLiteDatabase.ActiveDatabases
by replacing it with private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases and cleaning it up in SQLiteDatabase.onAllReferencesReleased(), following what was done in: aosp-mirror/platform_frameworks_base@e5360fb NOTE: in the Android project the reference is _not_ cleaned up in case the SQLiteDatabase instance is finalized. No such distinction is made in this commit.
1 parent 55bcf15 commit 7eb1d97

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

src/net/sqlcipher/database/SQLiteDatabase.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.io.FileOutputStream;
2828
import java.io.IOException;
2929
import java.io.OutputStream;
30-
import java.lang.ref.WeakReference;
3130
import java.text.SimpleDateFormat;
3231
import java.util.ArrayList;
3332
import java.util.HashMap;
@@ -73,6 +72,12 @@ public class SQLiteDatabase extends SQLiteClosable {
7372
private static final int EVENT_DB_OPERATION = 52000;
7473
private static final int EVENT_DB_CORRUPT = 75004;
7574

75+
// Stores reference to all databases opened in the current process.
76+
// (The referent Object is not used at this time.)
77+
// INVARIANT: Guarded by sActiveDatabases.
78+
private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases =
79+
new WeakHashMap<SQLiteDatabase, Object>();
80+
7681
public int status(int operation, boolean reset){
7782
return native_status(operation, reset);
7883
}
@@ -394,6 +399,10 @@ protected void onAllReferencesReleased() {
394399
mTimeClosed = getTime();
395400
}
396401
dbclose();
402+
403+
synchronized (sActiveDatabases) {
404+
sActiveDatabases.remove(this);
405+
}
397406
}
398407
}
399408

@@ -958,6 +967,7 @@ public static SQLiteDatabase openDatabase(String path, String password, CursorFa
958967
*/
959968
public static SQLiteDatabase openDatabase(String path, char[] password, CursorFactory factory, int flags, SQLiteDatabaseHook hook) {
960969
SQLiteDatabase sqliteDatabase = null;
970+
961971
try {
962972
// Open the database.
963973
sqliteDatabase = new SQLiteDatabase(path, password, factory, flags, hook);
@@ -978,7 +988,10 @@ public static SQLiteDatabase openDatabase(String path, char[] password, CursorFa
978988
}
979989
sqliteDatabase = new SQLiteDatabase(path, password, factory, flags, hook);
980990
}
981-
ActiveDatabases.getInstance().mActiveDatabases.add(new WeakReference<SQLiteDatabase>(sqliteDatabase));
991+
992+
synchronized (sActiveDatabases) {
993+
sActiveDatabases.put(sqliteDatabase, null);
994+
}
982995
return sqliteDatabase;
983996
}
984997

@@ -2335,25 +2348,18 @@ public synchronized void setMaxSqlCacheSize(int cacheSize) {
23352348
mMaxSqlCacheSize = cacheSize;
23362349
}
23372350

2338-
static class ActiveDatabases {
2339-
private static final ActiveDatabases activeDatabases = new ActiveDatabases();
2340-
private HashSet<WeakReference<SQLiteDatabase>> mActiveDatabases =
2341-
new HashSet<WeakReference<SQLiteDatabase>>();
2342-
private ActiveDatabases() {} // disable instantiation of this class
2343-
static ActiveDatabases getInstance() {return activeDatabases;}
2344-
}
2345-
23462351
/**
23472352
* this method is used to collect data about ALL open databases in the current process.
23482353
* bugreport is a user of this data.
23492354
*/
23502355
/* package */ static ArrayList<DbStats> getDbStats() {
23512356
ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
2352-
for (WeakReference<SQLiteDatabase> w : ActiveDatabases.getInstance().mActiveDatabases) {
2353-
SQLiteDatabase db = w.get();
2357+
2358+
for (SQLiteDatabase db : getActiveDatabases()) {
23542359
if (db == null || !db.isOpen()) {
23552360
continue;
23562361
}
2362+
23572363
// get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
23582364
int lookasideUsed = db.native_getDbLookaside();
23592365

@@ -2395,6 +2401,14 @@ private ActiveDatabases() {} // disable instantiation of this class
23952401
return dbStatsList;
23962402
}
23972403

2404+
private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2405+
ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2406+
synchronized (sActiveDatabases) {
2407+
databases.addAll(sActiveDatabases.keySet());
2408+
}
2409+
return databases;
2410+
}
2411+
23982412
/**
23992413
* get the specified pragma value from sqlite for the specified database.
24002414
* only handles pragma's that return int/long.

0 commit comments

Comments
 (0)