Skip to content

Method injection causes memory leak [SPR-10785] #15411

@spring-projects-issues

Description

@spring-projects-issues

Christian Schreder opened SPR-10785 and commented

Overview

Recently I recognized strange behavior in a project with around 700 tests running via Maven in one JVM. Some of the tests have different application contexts defined. As I run the tests I get an OutOfMemoryException. I managed to break it down to one place where a bean with method injection is defined. If I comment it out I have constant memory usage. With it, memory consumption is increasing. Reproduced on Windows 7 using JRockit 1.6.

For further investigation I wrote a reproducer. It is a simple maven project defining two beans where one bean has a method injection. I have 4 test classes with 1000 test methods per class and after each method the application context is rebuilt (via the @DirtiesContext annotation). Also I included a log file with activated gc-logging. I was also able to reproduce this behavior on Mac OS 10.6.8 with Sun's JDK 1.6.

Assumptions

  • ApplicationContext with method injection.
  • Several tests with different application contexts or tests which dirty the application context => what matters is that application contexts get built often.

Steps to Reproduce

Run all tests in one JVM (e.g. with maven).

Result

Memory consumption constantly increases until an OutOfMemoryException is thrown.


Analysis

The following table displays execution time, the number of classes loaded, and memory consumption when the test suite in the attached ZIP file are executed against various Java and Spring versions.

Spring 3.2.x

|| Spring Version || Java Version || Time || Classes || Memory |
| 3.2.7.RELEASE | JDK 1.6 | 1:54 | 6700 | 54 / 86 / 86 |
| 3.2.7.RELEASE | JDK 1.7 | 1:51 | 6629 | 45 / 82 / 86 |
| 3.2.7.RELEASE | JDK 1.8 | 1:44 | 6670 | 43 / 44 / 1082 |
| 3.2.8.BUILD-SNAPSHOT | JDK 1.6 | 1:42 | 2716 | 21 / 22 / 86 |
| 3.2.8.BUILD-SNAPSHOT | JDK 1.7 | 1:31 | 2629 | 17 / 22 / 86 |
| 3.2.8.BUILD-SNAPSHOT | JDK 1.8 | 1:24 | 2683 | 17 / 18 / 1082 |

Spring 4.0.x

|| Spring Version || Java Version || Time || Classes || Memory |
| 4.0.1.RELEASE | JDK 1.6 | 2:27 | 6761 | 54 / 83 / 86 |
| 4.0.1.RELEASE | JDK 1.7 | 2:22 | 6681 | 46 / 78 / 86 |
| 4.0.1.RELEASE | JDK 1.8 | 2:09 | 6739 | 43 / 44 / 1082 |
| 4.0.2.BUILD-SNAPSHOT | JDK 1.6 | 1:38 | 2758 | 22 / 22 / 86 |
| 4.0.2.BUILD-SNAPSHOT | JDK 1.7 | 1:56 | 2675 | 17 / 22 / 86 |
| 4.0.2.BUILD-SNAPSHOT | JDK 1.8 | 1:39 | 2741 | 18 / 19 / 1082 |

Key
  • OS: Mac OS X 10.9.1
  • Java Versions:
    JDK Version
    1.6 1.6.0_65-b14-462-11M4609
    1.7 1.7.0_51-b13
    1.8 1.8.0-b129
  • Time: in minutes
  • Classes: represent the number of classes loaded.
  • Memory: values are rounded and represent Used/Size/Max memory * 1,000,000 Bytes. For JDK 1.6 and 1.7, memory represents PermGen usage. For JDK 1.8, memory represents Metaspace usage.

Conclusion

As can be seen in the Analysis section, the fixes in Spring Framework 3.2.8.BUILD-SNAPSHOT and 4.0.2.BUILD-SNAPSHOT result in constant memory consumption and zero unnecessary CGLIB class generation (i.e., no longer one CGLIB class per method injected bean instance).

The following screenshots provide a visual comparison for Java 6.

Before Fix (Spring 3.2.7)

!memory usage - JDK 1.6 - Spring 3.2.7.png|thumbnail!

After Fix (Spring 4.0.2)

!memory usage - JDK 1.6 - Spring 4.0.2.png|thumbnail!


Affects: 3.0 GA

Attachments:

Issue Links:

Referenced from: commits 8028eae, 1ae3eba, f2a4537, bc87910

Backported to: 3.2.8

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions