我是一名c ++程序员,在找到JPA之后,我正在玩Java,而目前我的一些应用程序是神派。我从大学开始就没有触及java,我遇到了堆空间不足的问题。我正在使用下面的代码作为jdbc / jpa / lucene的非常严重测试的主要部分,但我继续获得随机的OutOfMemory异常。
EntityManager em = emf.createEntityManager();
Query q = em.createQuery("select p from Product p" +
" where p.productid = :productid");
Connection con = DriverManager.getConnection("connection string");
Statement st = con.createStatement();
IndexWriter writer = new IndexWriter("c:\\temp\\lucene", new StandardAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
ResultSet rs = st.executeQuery("select productid from product order by productid");
while (rs.next()) {
int productid = rs.getInt("PRODUCTID");
q.setParameter("productid", productid);
Product p = (Product)q.getSingleResult();
writer.addDocument(createDocument(p));
}
writer.commit();
writer.optimize();
writer.close();
st.close();
con.close();
我不会发布所有的createDocument,但它所做的只是实例化一个新的org.apache.lucene.document.Document并通过add(new Field ...)等添加字段。总共有大约50个字段大多数是短字符串(<32个字符)。
在我的新事物中,有什么东西是完全愚蠢的我正在做(或不做)会导致事情不被GC化吗?
是否有关于Java内存管理和滴答GC的最佳实践?
答案 0 :(得分:3)
我没有看到任何明显不合适的地方。如果您正在使用非常大的数据库,则可以尝试使用JVM调用中的-Xmx n
选项来增加堆大小。这通常不是最好的解决方案 - 只有在您知道工作集大小实际上大于默认堆大小时才会这样做。
您使用的是任何复杂的数据结构吗?如果对象之间有循环引用,则可能会阻止垃圾回收器清除无法访问的对象。如果您有任何手写数据结构,请确保显式地删除对已删除对象的引用,而不是执行缩小大小变量之类的操作。
答案 1 :(得分:2)
尝试使用SAP内存分析器。
https://www.sdn.sap.com/irj/sdn/wiki?path=/display/Java/Java+Memory+Analysis
这会读入转储文件,让您调查占用内存的内容。
答案 2 :(得分:2)
嗯...
使用Java和数据库的长期经验(an example post postgresSQL mysql oracle差异&gt;)告诉我,我们在执行此工作时使用的JDBC驱动程序经常遇到问题。
我有一段代码需要24/7全天候连接到数据库,并且由于驱动程序内存泄漏,JVM总是会在某些时候窒息。因此,我编写代码来捕获抛出的特定异常,然后采取越来越激烈的行动,包括放弃连接并重新连接,甚至在绝望中重新启动JVM,没有任何工作来清除问题情况。什么是PAIN必须编写它,但它直到DBMS供应商推出了一个新的JDBC驱动程序才能解决问题......我实际上只是保留了代码,以防万一!
......所以,你可能无所事事。
请注意,调用垃圾收集器是我使用的策略之一,但指标显示它很少有用。
此外,它可能不太清楚,但是在许多情况下(除非另外明确设置),ResultSets会保持与数据库引擎本身的持续连接,即使您只是阅读。并且,一些JDBC驱动程序允许您请求单向连接,但是谎言并返回双向连接!小心这个!
因此,最好将ResultSet对象卸载到其他对象中以保存值并尽快删除ResultSet对象。
祝你好运。 RTIII答案 3 :(得分:2)
可能你的永久生成空间不足。 检查堆栈跟踪是否包含类似java.lang.OutOfMemoryError:PermGen
的内容您可以使用jvm的以下参数增加此代的空间:-XX:MaxPermSize = 128m
垃圾收集期间不考虑永久代中的对象。 查看this page from sun以了解有关垃圾收集和JVM中不同代对象的更多信息。
答案 4 :(得分:0)
结果集中有多少项?如果有足够的记录,那么你将耗尽所有内存,因为在这种情况下没有收集任何垃圾,因为你正在向编写器执行addDocument,它将保存对你正在创建的所有文档的引用。
答案 5 :(得分:0)
Java维护着几个不同的内存池,并且其中任何一个内容都用完就会导致可怕的OutOfMermoryException。操作系统分配内存的问题也可以表现为OOM。
您应该会看到详细的堆栈跟踪 - 或者可能是应用程序目录中的错误转储文件 - 这可能会为问题提供更多线索。
如果您使用了一个不错的分析器 - 最近的Sun Java 6 JDK附带的JVisualVM可能就足够了 - 您可以观看所有不同的池并查看哪些池正在运行。