Memory leak while merging parent with No Cascade annotation with children

#1

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

#2

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
#3

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 :

https://www.objectdb.com/forum/1408

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

#4

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

ObjectDB Support

Reply