455 words

Memory leak while merging parent with No Cascade annotation with children

#1
2014-05-18 10:07

Hello support,

While tracking memory leak in my application i suspected a memory leak in the merging object db implementation.

The test case is the following, just run and watch the "Memory Used" by comparing Cascade.ALL (or Cascade.MERGE ) to nothing.

Tested with last version of Object Db ( 2.5.5_05 )

import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Persistence;
 
 
public final class MyTestCase {
 
    public static void main(String[] args)  {
 
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/test.tmp;drop");
 
        for (int n=0;n<100;++n) {
 
            memoryUsage();
 
            EntityManager em = emf.createEntityManager();
 
            System.out.println("n = " + n);
            for(int i=0;i<1000;++i) {
 
                MyEntity e = new MyEntity("parent" + String.valueOf(i));
                e.addChild(String.valueOf("child" + String.valueOf(i)));
                em.merge(e);
 
            }
 
            if (! em.getTransaction().isActive()) {
                em.getTransaction().begin();
            }
 
            em.getTransaction().commit();
            em.clear();
            em.close();
 
            System.gc();
        }
 
        emf.close();
    }
 
    @Entity
    public static class MyEntity {
 
        @Id
        private String name;
 
        @ManyToMany(cascade = {
                // No CascadeType.ALL //=> Huge memory leak while merging parent !
                // CascadeType.MERGE or CascadeType.ALL // => No memory leak
        })
        private List <MyEntityChild> lst = new ArrayList <MyEntityChild> ();
 
        MyEntity(String name) {
            this.name = name;
        }
 
        public void addChild(String name) {
            lst.add(new MyEntityChild(name));
        }
    }
 
    @Entity
    public static class MyEntityChild {
 
        @Id
        private String name;
 
        MyEntityChild(String name) {
            this.name = name;
        }
    }
 
    private static void memoryUsage() {
 
        int mb = 1024*1024;
 
        //Getting the runtime reference from system
        Runtime runtime = Runtime.getRuntime();
 
        System.out.println("##### Heap utilization statistics [MB] #####");
 
        //Print used memory
        System.out.println("Used Memory:"
            + (runtime.totalMemory() - runtime.freeMemory()) / mb);
 
        //Print free memory
        System.out.println("Free Memory:"
            + runtime.freeMemory() / mb);
 
        //Print total available memory
        System.out.println("Total Memory:" + runtime.totalMemory() / mb);
 
        //Print Maximum available memory
        System.out.println("Max Memory:" + runtime.maxMemory() / mb);
    }
}

Regards,

Xirt

xirt
xirt's picture
Joined on 2012-07-12
User Post #13
#2
2014-05-20 02:24

Thank you for this report and for the test case.

I can confirm that it demonstrates a memory leak when using reflection mode.

But the same test case works well with no memory leak when the entity class is enhanced
(e.g. running with -javaagent:C:\objectdb\bin\objectdb.jar).

We will try to fix it, but please be aware that reflection mode is not recommended (except for small tests or examples), because it is slower and it is more vulnerable for issues like this.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #1,885
#3
2014-05-20 15:54

Thx support,

My application is already running under objectdb javaagent but there is a problem.

Indeed, my beans are not correctly Enhanced, reason is my beans are created by Java Proxy.

- JAXB add some JAXBAccessor into the byte code.

- Google guava cache do some CGLIB proxy with my entities beans.

My conclusion is that the Enhancer is not able to process correctly customed dynamic class ... but i'm not a specialist of java reflection and injection stuff.

So i opened a dedicated thread for this problem here :

http://www.objectdb.com/database/forum/782

Edit 26/05 : I just found a workaround with my JAXB beans. But i think you should resolve the problem for reflection case.

Regards,

Xirt

xirt
xirt's picture
Joined on 2012-07-12
User Post #15
#4
2014-06-02 09:06

Build 2.5.5_06 includes a fix for this issue. Thank you for your report.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #1,918

Post Reply

Please read carefully the posting instructions - before posting to the ObjectDB website.

  • You may have to disable pop up blocking in order to use the toolbar (e.g. in Chrome).
  • Use ctrl + right click to open the browser context menu in the editing area (e.g. for using a browser spell checker).
  • To insert formatted lines (e.g. Java code, stack trace) - select a style in the toolbar and then insert the text in the new created block.
  • Avoid overflow of published source code examples by breaking long lines.
  • You may mark in paragraph code words (e.g. class names) with the code style (can be applied by ctrl + D).
  • Long stack traces (> 50 lines) and complex source examples (> 100 lines) should be posted as attachments.
Attachments:
Maximum file size: 32 MB
Cancel