It appears that it is being caused by the creation of an EntityManager. Currently, a new EntityManager is created each time a JSP is called. Each call to the EntityManager causes the PermGen to increase significantly.
We are not using Stateful or Stateless EBJs. Is there something special we need to do to ensure that the EntityManager is garbage collected?
how do you access the EntityManager? Through an EntityManagerfactory?
If so...you need to call EntityManager.close()!
Yes, the EntityManager was created from the EntityManagerFactory. We tried calling the EntityManager.close() method but the PermGen still increased each time.
We tested this by creating a JSP page that simply creates the EntityManager and calls the close() method right away. The PermGen space still increated.
Our application is a standard web-app, for which we recently moved to using 4.0.4RC1 and switched from session bean access and eager fetching to direct EntityManager access and lazy fetching (to simplify). Essentially now we're utilizing an EntityManagerFactory to get an EntityManager at the beginning of each request, using it throughout the request, and closing it at the end of the request (making sure that always, always happens of course).
What we're seeing is that after a rather low number of page requests (on the order of a dozen or two), we get:
17:04:50,756 ERROR [jsp] Exception happened while executing page: PermGen space java.lang.OutOfMemoryError: PermGen space
17:04:58,038 ERROR [[jsp]] Servlet.service() for servlet jsp threw exception java.lang.OutOfMemoryError: PermGen space
This raises two questions, one being whether anyone's had similar memory leak issues when doing this; the second being whether it's more appropriate to try to minimize EntityManager creation. For instance, could a web app use a singleton EntityManager reference? Any multithreading issues with that? We could associate an EntityManager with a user session and re-use it, but that risks instances sticking around until each session expires.
Apologies if these questions are basic; the EJB3 world is a new one for us. Thanks for your assistance.
I should also add to my post above the question of whether the previously-accepted Hibernate approaches are generally still applicable. If so, is it correct to assume that a single EntityManagerFactory should be used, and that it's proper to get a new EntityManager for each request? As I recall, the EntityManager is not threadsafe, but I'm not sure if that's still the case.
Thanks again for your assistance.
Do you do
Persistence.createEntityManagerFactory() every time too? If so, you must close the EntityManagerFactory as well. You chould be caching your EntityManagerFactory in the WAR's application context.
BTW, why did you rip out your session beans? They are supposed to make things simpler, not more complicated. Just curious thanks.
All previously accepted apporach are still acceptable, you just have to replace the session word by the entitymanager word and sessionfactory word by entitymanagerfactory word.
I've tested a small open / process /close loop 5,000,000 and do not encounter any OOME nor Perm size increase.
Bill are you pooling the em and calling clear() rather than close()?
We were using Stateless session beans that themselves used the EntityManager to find, update and remove entity beans. The stateless session beans were being used by JSP in our WAR. We were noticing some performance issues because our Entity beans were set to EAGER fetch. So in order to use LAZY fetch, we needed to use a local EntityManager. So we moved to using standard classes instead of the stateless session beans since we did not find a way to keep the returned entity bean attached to the EntityManager.
Is there another way of doing LAZY fetch on entities when the EntityManager used to retrieve the beans resides in a stateless session bean?
JBoss Seam has this notion of keeping the persistence context opened long enought for the JSP rendering.
What would be great if to use a profiler to detect the causes of this leak. I don't see how this could happen unless, like Bill said, you create the EMF again and again.
Looks as though the culprit was that in fact an EntityManagerFactory was being created for each page request, which is obviously not good. We're now using a singleton EMF, and creating an EntityManager at the beginning of each request (and closing it at the end). This appears to have taken care of the problem, though we need to do some more testing to make sure; initial results show that the PermGen space is still growing, but much much more slowly.
A possibly related question: could someone point me to a summary of the difference between calling EntityManagerFactory.getEntityManager() and createEntityManager()? In Hibernate the getEF() is supposed to be a "container-managed" call, but I'm not sure what this means now in EJB3. If one is more likely to be efficient or safer, that would be good to know.
don't worry about it. getEntityManager is going away in next spec revision. getEntityManager is supposed to return a transaction-scoped entitymanager.
Regarding the original memory leak issue, looks as though we're still encountering it, but much less frequently. It seems suspiciously linked to hot redeploys of the web app; the more redeploys done without restarting JBoss, the more quickly we encounter the PermGen out of memory error. Anyone seeing this with 4.0.4RC1?