Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-1638

Memory leak in ProxyFactory when using CGLIB proxies

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.6
    • Fix Version/s: 2.0 M4
    • Component/s: Core:AOP
    • Labels:
      None
    • Last commented by a User:
      false

      Description

      I have a memory leak when using the ProxyFactory.

      This has been tested with the following configuration :

      • cglib-nodep-2.1_3.jar
      • spring 1.2RC2 and spring 1.2.6
      • IBM's JVM and SUN's JVM

      Here is the unit test to demonstrate the problem :

      import junit.framework.TestCase;

      import org.aopalliance.intercept.MethodInterceptor;
      import org.aopalliance.intercept.MethodInvocation;
      import org.springframework.aop.framework.ProxyFactory;
      import org.springframework.aop.support.NameMatchMethodPoi ntcutAdvisor;

      public class TestProxyFactoryMemoryLeak extends TestCase {

      public void testMemoryLeak() {
      Object target = new Object();
      MethodInterceptor methodInterceptor = new DummyMethodInterceptor();

      while (true)

      { ProxyFactory proxyFactory = new ProxyFactory(); NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(methodInterceptor); advisor.addMethodName("dummy"); proxyFactory.addAdvisor(advisor); proxyFactory.setProxyTargetClass(true); proxyFactory.setTarget(target); proxyFactory.getProxy(); }

      }

      private class DummyMethodInterceptor implements MethodInterceptor {
      public Object invoke(MethodInvocation methodInvocation) throws Throwable

      { return methodInvocation.proceed(); }

      }
      }

      Thanks
      Eric Ballet-Baz

        Activity

        Hide
        asenft Andreas Senft added a comment -

        Could this be related with the CGLIB class-caching issues elaborated here?
        http://forum.springframework.org/showthread.php?t=13361

        Regards,
        Andreas

        Show
        asenft Andreas Senft added a comment - Could this be related with the CGLIB class-caching issues elaborated here? http://forum.springframework.org/showthread.php?t=13361 Regards, Andreas
        Hide
        robh Rob Harrop added a comment -

        As Andreas points out this is an issue related to class caching in CGLIB. Right now we take quite a conservative approach and assume that pointcuts, advisors and advice are only equal if they pass the == test. To make this work in your example you should create just a single instance of the NameMatchMethodPointcutAdvisor and reuse it. That way you will see that the same class is reused. A good test of this is to try creating around 5000 instances of the proxy with a VM size of 24MB. When using the same instance of the advice and advisor you will see that all 5000 are created in around 2 seconds. When using new instances each time you will never even create 5000 proxies and it will take a long timeto get the around 3000 proxies where the JVM will die.

        For the 1.2.7 release we are going to leave this as is with the two known workarounds remaining:

        1. Use JDK proxies - much more efficient overall when creating many proxies programatically.
        2. When using CGLIB, reuse the Advisor, Advice and Pointcut instances where possible or implement equals() and hashCode().

        For Spring 2.0, we will take a much less conservative and much more optimal approach for testing proxy class equality.

        Rob

        Show
        robh Rob Harrop added a comment - As Andreas points out this is an issue related to class caching in CGLIB. Right now we take quite a conservative approach and assume that pointcuts, advisors and advice are only equal if they pass the == test. To make this work in your example you should create just a single instance of the NameMatchMethodPointcutAdvisor and reuse it. That way you will see that the same class is reused. A good test of this is to try creating around 5000 instances of the proxy with a VM size of 24MB. When using the same instance of the advice and advisor you will see that all 5000 are created in around 2 seconds. When using new instances each time you will never even create 5000 proxies and it will take a long timeto get the around 3000 proxies where the JVM will die. For the 1.2.7 release we are going to leave this as is with the two known workarounds remaining: 1. Use JDK proxies - much more efficient overall when creating many proxies programatically. 2. When using CGLIB, reuse the Advisor, Advice and Pointcut instances where possible or implement equals() and hashCode(). For Spring 2.0, we will take a much less conservative and much more optimal approach for testing proxy class equality. Rob
        Hide
        robh Rob Harrop added a comment -

        I'm shifting this to RC1 due to time pressures. The most comprehensive and desirable fix here requires a reasonable amount of work and can also be coupled with a general tidy up in that area. I'll be doing all of this work as part of the RC1 push.

        Rob

        Show
        robh Rob Harrop added a comment - I'm shifting this to RC1 due to time pressures. The most comprehensive and desirable fix here requires a reasonable amount of work and can also be coupled with a general tidy up in that area. I'll be doing all of this work as part of the RC1 push. Rob

          People

          • Assignee:
            robh Rob Harrop
            Reporter:
            ericbb Eric Ballet Baz
            Last updater:
            Trevor Marshall
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              11 years, 22 weeks, 4 days ago