OutOfMemoryError
Glassfishで長時間実行されているバックグラウンドプロセスに遭遇しています。メモリ分析によると、エラーがスローされた時点で、ヒープの50%がcom.mysql.JDBC4ResultSet
(28.1%)とcom.mysql.jdbc.StatementImpl
(22.1%)のインスタンス専用であることが示されています。
私のコードは、JDBCオブジェクトがスコープを失うとガベージコレクションされることを前提に構成されていますが、これは明らかにそうではありません。私はもともとJPAを使用してこれを行いましたが、メモリ負荷が爆発的に増加したため、JDBCに戻りましたが、JDBCステートメントとResultSetへの参照で構成される大量のメモリリークが発生しています。
したがって、Glassfishがこれらのクエリをキャッシュしているかどうか、およびそれを無効にするにはどうすればよいか疑問に思っています。データオブジェクトは非常に大きく、キャッシュする必要はありません。
以下に、1つのクラスと2つのメソッド(簡潔にするために変更)で構成されるコードの構造を含めました。
@Stateless
public class WSDFileCollector implements Collector {
@PersistenceContext
private EntityManager em;
@Override
@Asynchronous
public void run(final CollectorEntity collector) throws SQLException {
final Connection connection = em.unwrap(Connection.class);
final String table = "tmp_sat_" + collector.getSite().getId();
final String column = "filename";
try {
// Create temporary table
// Scan files & folders under a given directory.
// Load filenames into MySQL Temporary table.
final Statement statement = connection.createStatement();
final ResultSet results = statement.executeQuery("SELECT filename FROM temporary_table WHERE filename NOT IN (SELECT filename FROM existing_files");
while (results.next()) {
final File file = new File(collector.getPath(), results.getString("filename"));
if (file.isFile()) {
extractAndSave(file, collector);
}
}
} finally {
// Delete temporary table
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void extractAndSave(final File file, final CollectorEntity collector) {
final Connection connection = em.unwrap(Connection.class);
try {
// Begin a transaction
// INSERT new file into existing_files
// Scan the file, extract data and insert into multiple database tables.
// Commit transaction
} catch (final SQLException | FileNotFoundException ex) {
// Rollback transaction
}
}
}