2

最大 30 個のオブジェクトをクエリしようとすると、このエラーが発生します。各オブジェクトには、100x100 ARGB_8888 ビットマップ データ~ 39kbのフィールド byte[]があります。

OrmLite 4.45 バージョンを使用しています。Samsung GT n8000 タブレット (最大ヒープ サイズ 64MB)

スタックトレースは次のとおりです。

android.database.sqlite.SQLiteException: unknown error (code 0): Native could not create new byte[]
    at android.database.CursorWindow.nativeGetBlob(Native Method)
    at android.database.CursorWindow.getBlob(CursorWindow.java:403)
    at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
    at com.j256.ormlite.android.AndroidDatabaseResults.getBytes(AndroidDatabaseResults.java:161)
    at com.j256.ormlite.field.types.ByteArrayType.resultToSqlArg(ByteArrayType.java:41)
    at com.j256.ormlite.field.BaseFieldConverter.resultToJava(BaseFieldConverter.java:24)
    at com.j256.ormlite.field.FieldType.resultToJava(FieldType.java:798)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:60)
    at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:270)
    at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:161)
    at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:187)
    at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:263)
    at com.j256.ormlite.dao.EagerForeignCollection.(EagerForeignCollection.java:37)
    at com.j256.ormlite.field.FieldType.buildForeignCollection(FieldType.java:781)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:82)
    at com.j256.ormlite.android.AndroidDatabaseConnection.queryForOne(AndroidDatabaseConnection.java:186)
    at com.j256.ormlite.stmt.mapped.MappedQueryForId.execute(MappedQueryForId.java:38)
    at com.j256.ormlite.field.FieldType.assignField(FieldType.java:540)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:71)
    at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:270)
    at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:161)
    at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:187)
    at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:263)
    at com.j256.ormlite.stmt.QueryBuilder.query(QueryBuilder.java:319)
    at com.j256.ormlite.stmt.Where.query(Where.java:485)
    at com.j256.ormlite.dao.BaseDaoImpl.queryForEq(BaseDaoImpl.java:243)    

ここにlogcatがあります:

05-16 14:05:24.561: D/dalvikvm(4163): GC_CONCURRENT freed 1247K, 10% free 18046K/19911K, paused 11ms+3ms, total 30ms
05-16 14:05:24.561: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 10ms
05-16 14:05:24.686: D/dalvikvm(4163): GC_CONCURRENT freed 119K, 4% free 19922K/20743K, paused 11ms+2ms, total 28ms
05-16 14:05:24.686: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 15ms
... whole ton of these
05-16 14:05:27.261: D/dalvikvm(4163): GC_CONCURRENT freed 109K, 2% free 62754K/63495K, paused 12ms+5ms, total 36ms
05-16 14:05:27.261: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 20ms
05-16 14:05:27.366: I/dalvikvm-heap(4163): Clamp target GC heap from 65.738MB to 64.000MB
  • このようなメモリ使用量の急速な増加は正常ですか?
  • クエリをチャンクに分割し、それらの個別のクエリ間で明示的に System.gc() を呼び出すことについてどう思いますか?

ありがとう!

4

1 に答える 1

2

このようなメモリ使用量の急速な増加は正常ですか?

いいえ、そうではありません。

クエリをチャンクに分割し、それらの個別のクエリ間で明示的に System.gc() を呼び出すことについてどう思いますか?

いいえ、これで問題が解決する可能性はほとんどありません。根本的なメモリの問題を直接解決する必要があります。

投稿で提供しなかったコードとエンティティを確認した後、これはORMLiteの問題ではなく、エンティティの問題です。

あなたは のGalleryを持っていPhotoます。各写真には、おそらく 50+k のバイト イメージ データの大きな配列があります。問題は、Galleryが の積極的な外部コレクションを持っていることですPhoto:

@ForeignCollectionField(eager = true)
private ForeignCollection<Photo> photos;

そして、それぞれPhotoにその親の自動更新バージョンがありGalleryます。

@DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = GALLERY)
private Gallery gallery;

これにより、ORMLite が次のような処理を行う熱心なフェッチ ループが設定されます。

  1. ORMLiteGalleryがメモリにロードしようとするたびに...
  2. コレクションが集中しているため、別のクエリを実行して、 に関連付けられているすべての写真Galleryをメモリにロードするよう求められています。
  3. これらのインスタンスのそれぞれについて、親が自動更新されるためPhoto、関連付けられた をメモリに取得するために別のクエリを実行するよう求められています。Gallery
  4. そのためにGallery、すべてPhotoの をメモリにロードするよう求められます。
  5. ... ORMLite には実際にエスケープがありますが、それでも 3 レベル下がります。

ORMLite にはGalleryandPhotoインスタンスの魔法のビューがないため、親Galleryを s の外部フィールドにアタッチしますPhoto。これが必要な場合は、以下のObjectCache解決策を参照してください。

これを修正するには、いくつかの方法があります。

  • 使用しないことをお勧めしforeignAutoRefresh = trueます。写真の が必要な場合は、Galleryを実行して取得できますgalleryDao.refresh(photo.getGallery())。これにより、熱心なフェッチのチェーンが中断されます。
  • photosコレクションを熱心にしないようにすることもできます。遅延ロードされたコレクションは、データベースに何度もアクセスしますが、サイクルも中断します。
  • ただし、すべての熱心なコレクションと更新が本当に必要な場合は、 ObjectCache. 頻繁にキャッシュをクリアする必要があるかもしれませんが、各 DAO はキャッシュを調べて、熱心なフェッチ ループが進行している場合でも同じオブジェクト エンティティを返します。

    galleryDao = getHelper().getRuntimeExceptionDao(Gallery.class);
    galleryDao.setObjectCache(true);
    photoDao = getHelper().getRuntimeExceptionDao(Photo.class);
    photoDao.setObjectCache(true);
    ...
    // if you load a lot of objects into memory, you must clear the cache often
    galleryDao.clearObjectCache();
    photoDao.clearObjectCache();
    
于 2013-07-23T14:20:13.177 に答える