Search code examples
javamemory-leakspersistenceeclipselink

How can I prevent Eclipselink from consuming all memory with the cache?


My application extracts large amounts of geometry data. I use Eclipselink 2.4.1 to persist that data in a MySQL database. The application works batch-style, i.e. I gather a set of data, then persist it, and continue with the next set, persist it and so on. Another application later reads that data and processes it, but this question is only about the first application that gathers the data.

The data-gathering application runs for quite some time. I use a fixed set of EntityManagers which are created at startup and live until the application is finished. Extraction is multithreaded and there is one EntityManager per Thread. My problem is that no matter how I configure the cache, after a while EclipseLink eats up all the memory and after a while I get an OutOfMemoryError.

I used VisualVM to extract heap dumps which I analyzed using Eclipse Memory Analyzer. A suspicious amount of memory is held by EntityManagerImpl.extendedPersistenceContext.cloneMapping. This map holds references to my geometry data objects. Over time, this map gets hundreds of megabytes in size and that's what causes the out of memory error.

I have already tried the following:

  • I use weak references by configuring eclipselink.persistence-context.reference-mode=weak. I have verified that EntityManagerImpl.extendedPersistenceContext.cloneMapping is of type IdentityWeakHashMap. From the documentation about weak caches I would expect that using reference mode weak solves the problem. Unfortunately, the garbage collector still does not claim the entries and I keep getting out of memory errors.
  • I tried to turn off caching completely with eclipselink.cache.shared.default=false. The problem persists.

Does anybody have a suggestion as to what's going on here and how I could solve that problem? I'm also open to suggestions how to circumvent the problem.


Solution

  • A few things.

    First, you should not keep long lived EntityManagers. You should create a new EntityManger per transaction, or per request.

    Second, ensure you application (static variables, etc.) is not holding references to the objects, if anything is referencing the object it will not garbage collect.