Reputation: 339
I have a question about the memory consumption of an application I'm in the early stages of developing at a university. When I launch a class that extends JFrame that serves as a login manager, the object consumes this much RAM:
While this JFrame is displayed, the program consumes around 42 MB of memory at any given time. This JFrame allows a user to login and access a medical records system. When the user logs in, the login manager is not simply made to be not visible; it is disposed of with the .dispose() function. The medical records system is then launched.
When the second class is launched (also extending JFrame), the program consumes this much RAM:
...roughly 66 MB at any given time. This makes sense, as this JFrame object is larger and requires more variables, leading to the object consuming more space. There is a 'log off' button on this JFrame which disposes of the medical records system JFrame object and creates a new login manager JFrame object when pressed.
Intuitively, I would think that because the medical records system was disposed of and the login manager is the only part of the application running, that the memory consumption of my program would drop to 42 MB of memory being consumed at any given time. This is not the case.
The memory consumption of the application remains at 66 MB. When I noticed this, my first thought was that perhaps the .dispose() function doesn't really free up the memory allocated to an object like I thought it did. If this were the case, then repeatedly logging in and out of my medical records system should continuously raise the amount of memory my application consumes as more and more objects are created. However, this is not the case either.
When I logged in and out of my medical records system, the memory consumption of my application stayed around 66 MB. My second thought was that perhaps because the largest amount of memory my application had consumed at one time while running was 66 MB, that the running Java program would hold on to this amount of memory for the duration of its lifespan despite whether it actually needs 66 MB of space or not. This space could then be 'recycled' and used again if the program had need for it. However, this does not seem to be the most efficient way of doing things. If this were the case, a program tasked with sorting an array of millions of elements and using a recursive algorithm such as a merge sort that would take up a large amount of space and then give it back, would be forced to hold on to the largest amount of space consumed by the program at any given time. This would freeze up an unnecessary amount of memory, and doesn't seem like it could be the case.
I tell you all of this so that you can know how I came to ponder these questions: How does Java handle memory consumption when objects are created and disposed of? How does this apply to my situation in particular?
Upvotes: 0
Views: 110
Reputation: 2776
As some of the coments already suggested, you are looking at the wrong number. Basically, Java uses its own memory-management and the ups and downs of your memory consumption can not be monitored using a task-manager or top.
Java allocates memory whenever the current amount of memory is insufficient to handle the task at hand and your memory-parameters (-Xmx) allow it to do so. Once objects are freed within the Java VM, the memory will not be freed by the Java process, but the VM will reserve that memory to be prepared for the next object allocations.
Memory will be freed by a garbage collector. This will be triggered by events like a full memory (or a manual System.gc() call). The garbage collector will identify all objects no longer reachable and free the space, they consume. Free in that case means: for new Java objects, not for the underlying OS. This is the reason why you will typically see an increasing memory consumption throughout a Java execution and virtually none memory reduction. (There is a special case, when the heuristic of the Java VM determines, it has already too much memory allocated and will return it to the OS)
Things are still more complex, as the Java VM manages the memory in a generational model with memory areas for young and old objects seperated from one another. Objects are allocated in the young spaces and grow older with every garbage-collection. At one point, objects are moved from young to old spaces. This is a question of garbage-collection efficiency.
As for observing all of this within a running VM, I will second the proposal of JVisualVM (although I would add, it is for your case only useful with the Visual GC Plugin), but I would also throw JConsole into the ring. For some reason I don't understand, Oracle removed the capability of monitoring old and young memory spaces differentiated in the step from JConsole (the predecessor of JVisualVM) to JVisualVM.
I think your studies will fail if you do not understand the generational memory model of Java and its implication towards overall memory consumption. As a starting point, I would suggest this article: Understanding the Java Memory Model and Garbage Collection
Upvotes: 1