0

我所有的业务方法都会创建一个新的 EntityManager 并在 finally 块中显式关闭它们。

            EntityManagerFactory entityManagerFactory = PersistenceManager.getInstance().getEntityManagerFactory(); //Singleton
            EntityManager em = entityManagerFactory.createEntityManager();
            EntityTransaction tx = em.getTransaction();
            try {
                tx.begin();
                em.persist(someEntity);
                tx.commit();

            } 
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                if (em!=null) {
                    em.close();
                }
            }

我定义了一个非常基本的 persistence.xml 文件。除了数据库连接信息之外,我并没有真正指定任何其他内容。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="db" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>package.class</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.logging.level" value="INFO" />
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
            <property name="javax.persistence.jdbc.url"
                value="url" />
            <property name="javax.persistence.jdbc.user" value="scott" />
            <property name="javax.persistence.jdbc.password" value=tiger" />
        </properties>
    </persistence-unit>
</persistence>

我在应用程序中看到的行为是分配的内存开始增长并最终达到最大限制,直到我开始出现内存不足错误。一段时间后,这些错误清除,JVM 分配的堆恢复到最大值的 95% 左右。我假设此时发生了 GC,尽管我没有附加分析器来确认。

这被认为是默认行为吗?调整缓存的一些最佳实践是什么。我可以在 persistence.xml 文件中设置哪些属性来限制最大缓存大小?我可以在全球范围内进行还是需要为每个实体类定义它?

4

1 回答 1

1

如果不使用分析器查看它,很难说出是什么保留了你的记忆。最常见的原因通常是重用 EntityManager 而不清除它们,因为 EntityManager 需要在其生命周期内保留每个托管实体,除非被清除。您没有使用您显示的持久实体的代码来执行此操作,但您没有显示您如何读取它们,因此它可能是可能的,并且在用户自己管理 EntityManagers 而不是让容器执行时更常见它为他们。

要回答有关 EclipseLink 缓存的问题:EclispeLink 有一个二级缓存,它将保留内存。此处显示了不同的缓存类型和选项 http://www.eclipse.org/eclipselink/documentation/2.4/concepts/cache002.htm 默认情况下,它使用一个softweakidentitymap,它有两个部分;使用软引用的缓存和使用弱引用的标识映射。如果您的应用程序不再被引用,软引用允许对对象进行垃圾回收,并且默认情况下每个描述符的大小为 100。

JPA 的缓存选项在此页面http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching上进行了讨论 ,您可以关闭共享缓存以查看这是否有助于您的应用程序。我会很惊讶它有帮助。您提到在垃圾收集发生后仍保留 95% 的应用程序内存,这表明应用程序仍然具有对资源的引用。

我建议您检查内存中的内容并评估您的应用程序中是否存在问题,或者只是您的应用程序需要比配置更多的内存量。

于 2013-02-15T14:15:11.360 回答