spring annotation-based configuration - memory consumption too high?
java, jvm, spring, spring-annotations
Solution
At startup a large number of `java.lang.reflect.Method` objects are created.
These objects are eligible for garbage collection, but in the case of your application it probably causes too many eden collections which results in high startup times.
Most of these `java.lang.reflect.Method` objects are allocated at the following site:
These seem to be created when Spring tries to find setters on `AnnotationConfigTestFrame` which inherits lots of methods from `java.awt` and `javax.swing` super classes. I did not read through the relevant code closely, but as a quick test to verify this hypothesis, I did the following:
@Service
public class AnnotationConfigTestFrame /* extends JFrame */
{
public static void main(String[] args) throws InterruptedException
{
ApplicationContext ctx = new AnnotationConfigApplicationContext(AnnotationConfigTestFrame.class);
AnnotationConfigTestFrame frame = (AnnotationConfigTestFrame) ctx
.getBean("annotationConfigTestFrame");
// frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
// frame.setVisible(true);
waitABit();
printRuntimeStats();
System.exit(0);
}
}
i.e. made `AnnotationConfigTestFrame` not inherit from `javax.swing.JFrame`. Now the memory usage for looking up the bean is reasonably low!
This might give you hints for debugging this further.
Problem
As I noticed crazy high RAM usage on my client application (Swing-based), I started looking into it and it seems like this is somehow related to Annotation-based configuration in Spring. As you will see in my edits below, i realized that this occurs only on 64-Bit JVM. See the following testcode: xml-based configuration ``` <beans ....> <bean id="xmlConfigTest" class="at.test.XmlConfigTest" /> </beans> public class XmlConfigTest extends JFrame { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml"); XmlConfigTest frame = (XmlConfigTest) ctx.getBean("xmlConfigTest"); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setVisible(true); } } ``` Uses up about 32MB memory, which seems ok to me. Now the same with annotation based configuration: ``` @Service public class AnnotationConfigTestFrame extends JFrame { public static void main(String[] args) throws InterruptedException { ApplicationContext ctx = new AnnotationConfigApplicationContext("at.test"); AnnotationConfigTestFrame frame = (AnnotationConfigTestFrame) ctx .getBean("annotationConfigTestFrame"); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setVisible(true); } } ``` Not only takes it noticeable longer to open the frame, but the memory consumption sky-rockets to 160MB memory on startup and then levels off at about 152MB, which seems really high to me. And remember, this is only the most basic case, the client application i develope atm eats up over 400MB already, which is just too much for older machines. Does anyone have an explanation for this behaviour? I don't understand.. (Using 3.1.1.RELEASE here btw.) edit* As suggested by axtavt, i also tried to construct the AnnotationConfigApplicationContext directly with the Test-Class as Argument, so that no classpath-scan is necessary. Didn't changed anything about the memory consumption unfortunately. edit 2 removed, see edit 3 edit 3 I now tested on the same machine (Windows 7 64-Bit) with both 32-Bit and 64-Bit JVM and the test-programms from above. This are the results: xml based configuration: ``` 32-Bit JVM: 16MB 64-Bit JVM: 31MB ``` annotation bassed configuration: ``` 32-Bit JVM: 17MB 64-Bit JVM: 160MB ``` So on 32-Bit JVM both proramms are close, which is pretty much what i would expect. On 64-Bit though, this is different. Even the first programm uses twice as much memory on 64-Bit, which already seems to be too much. Still it's nothing against the second program, which uses nearly 10 times more memory on 64-Bit. edit 4 Now tested under ubuntu too -> same effect. Still no idea why this is happening though. This is really a dealbreaker for me