我OutOfMemoryError
在 Glassfish 上运行了一个长时间运行的后台进程。内存分析表明,在抛出错误时,50% 的堆专用于com.mysql.JDBC4ResultSet
(28.1%) 和com.mysql.jdbc.StatementImpl
(22.1%) 的实例。
我的代码的结构是假设我的 JDBC 对象一旦失去范围就会被垃圾收集,但显然情况并非如此。我最初使用 JPA 执行此操作,但内存负载爆炸式增长,因此我恢复为 JDBC,但仍然出现大量内存泄漏,包括对 JDBC 语句和结果集的引用。
所以我想知道 Glassfish 是否正在缓存这些查询以及如何禁用它,数据对象非常大,我真的不需要缓存它们。
我在下面包含了由一个类和两个方法组成的代码结构(为简洁起见进行了修改)。
@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
}
}
}