Reputation: 3479
I'm trying to tune my JSF application memory consuption by setting JVM arguments because I'm getting out of memory error.
I'm able to increase memory heap and restart the server twice a day, but it's not a solution...
JVM arguments:
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSClassUnloadingEnabled
-XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=30
-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
-XX:ParallelCMSThreads=2
-XX:+UseCMSCompactAtFullCollection
-XX:+DisableExplicitGC
-XX:MaxHeapFreeRatio=70
-XX:MinHeapFreeRatio=40
-XX:MaxTenuringThreshold=30
-XX:NewSize=512m
-XX:MaxNewSize=512m
-XX:SurvivorRatio=2
-XX:PermSize=150m
-Xms1024m
-Xmx1024m
Everything seems to work fine, tenured space is at 0 MB, eden space is continuosly cleared but survivor space is still growing and when it reach its limit, object are moved to tenured space and never been released. And after half a day of running application I get the out of memory error. So I have to schedule automatical restarts of tomcat server.
So I think, there must be some problem in my application, because its memory consuption is too high for such a small appl (about thousands movements in database per day).
There is part of my code:
Bean.java
/* save datalist */
public void save()
{
session = DaoSF.getSessionFactory.openSession();
try
{
Dao.save(dataList);
}
catch (Exception e) {...}
finally
{
session.close();
}
}
Dao.java
public static void save(List<? extends Object> dataList)
{
for (Object dataItem : dataList)
{
save(dataItem);
}
}
public static void save(Object dataItem)
{
try
{
Transaction tx = session.beginTransaction();
session.save(dataItem);
tx.commit();
}
catch(Exception e) {....}
}
DaoSF.java
public class DaoSF implements Serializable
{
private static final long serialVersionUID = 1L;
private static SessionFactory sessionFactory;
private static Session hibSession;
private static synchronized void initSessionFactory
{
Configuration config = new Configuration();
config.configure("hibernate.cfg.xml");
sessionFactory = config.buildSessionFactory();
hibSession = sessionFactory.getCurrentSession();
}
public static SessionFactory getSessionFactory
{
initSessionFactory;
return sessionFactory;
}
public static Session getSession()
{
return hibSession;
}
}
Could you tell me, what are the best practices in saving (updating, deleting) of object to database so that the saved object don't stay in memory?
Upvotes: 3
Views: 5501
Reputation: 12538
Try this. It's not yet perfect, but I think you must get rid of the static session attribute in Dao. See hibernate docs: http://docs.jboss.org/hibernate/envers/3.5/javadocs/org/hibernate/Session.html:
It is not intended that implementors be threadsafe. Instead each thread/transaction should obtain its own instance from a SessionFactory.
You can also obtain the session inside Dao itself, so that Bean does not have any knowledge of the underlying persistence mechanisms, but I did not want to change that much.
Bean.java
/* save datalist */
public void save() {
Session session = nlul;
try {
session = DaoSF.getSessionFactory.openSession();
/* one instance per call,
* ready for garbage collection after leaving this method
*/
Dao mydao = new Dao(session);
mydao.save(dataList);
} catch (Exception e) {...
} finally {
if (sessioN != null)
session.close();
}
}
Dao.java
private Session mysession = null;
public Dao(Session mysession) {
this.mysession = mysession;
}
public void save(List<? extends Object> dataList) {
for (Object dataItem : dataList) {
save(dataItem);
}
}
public void save(Object dataItem) {
try {
Transaction tx = session.beginTransaction();
this.mysession.save(dataItem);
tx.commit();
}
catch(Exception e) {....}
}
Upvotes: 3
Reputation: 54836
It is extremely unlikely that your memory issues are directly related to anything you are doing with respect to saving/deleting/updating objects in your database. The PermGen
space is generally not used for any user-level objects. It is used for things that are meant to never be deallocated, such as class definitions, internal bits of JVM state, and the like.
If there was an issue with how you are managing your data objects, you would be seeing an OutOfMemoryError
complaining about there being no heap space left. But to answer your question, generally speaking your data objects will be garbage-collected on the next garbage collection pass that runs after they leave scope (meaning that you no longer have a reference to them anywhere). I suspect you are handling this fine already, as you are not getting OutOfMemoryError
issues.
If you are out of PermGen
space, it is probably because your application is using a large number of libraries. Sadly, the only way to fix this is to increase the PermGen
size, like:
-XX:PermSize=256m
Note that this will essentially decrease the amount of heap-space that is available to your application, so it is usually wise to increase your total JVM memory allocation by a corresponding amount, like:
-Xmx1130m
Give that a try and see if it works any better for you.
Upvotes: 4
Reputation: 24747
If you have a "PermGen: Out of Memory", it is not very related to any eden, survivor nor tenured space.
It is happening on permgen, "Non-Heap" part, which is related to -XX:PermSize=150m. Try a larger size of it.
Or, otherwise, there may be a memory leak happening on the JSP/servlet compiler/classloader/spring that too may Classes occupied the allocated memory. Try to reduce number of classes(not instance0 icuding proxy or AOP generated classes.
Upvotes: 2