简体   繁体   English

Java中对象的内存消耗

[英]Memory consumption by objects in Java

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: 当我启动扩展用作登录管理器的JFrame的类时,该对象将消耗大量RAM:

在此处输入图片说明

While this JFrame is displayed, the program consumes around 42 MB of memory at any given time. 当显示此JFrame时,该程序在任何给定时间消耗大约42 MB的内存。 This JFrame allows a user to login and access a medical records system. 该JFrame允许用户登录和访问病历系统。 When the user logs in, the login manager is not simply made to be not visible; 当用户登录时,不会简单地使登录管理器不可见。 it is disposed of with the .dispose() function. 它由.dispose()函数处理。 The medical records system is then launched. 然后启动病历系统。

When the second class is launched (also extending JFrame), the program consumes this much RAM: 当第二个类启动时(也扩展了JFrame),该程序将消耗大量RAM:

在此处输入图片说明

...roughly 66 MB at any given time. 在任何给定时间大约66 MB。 This makes sense, as this JFrame object is larger and requires more variables, leading to the object consuming more space. 这是有道理的,因为此JFrame对象更大并且需要更多变量,从而导致该对象占用更多空间。 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. 此JFrame上有一个“注销”按钮,该按钮处理病历系统JFrame对象,并在按下时创建一个新的登录管理器JFrame对象。

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. 凭直觉,我认为由于医疗记录系统已经废弃,而登录管理器是运行的应用程序的唯一组成部分,因此我的程序的内存消耗在任何给定时间都会降至42 MB。 This is not the case. 不是这种情况。

The memory consumption of the application remains at 66 MB. 应用程序的内存消耗保持在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. 当我注意到这一点时,我首先想到的是.dispose()函数可能并没有像我认为的那样真正释放分配给对象的内存。 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. 当我登录和退出医疗记录系统时,我的应用程序的内存消耗保持在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. 我的第二个想法是,也许是因为我的应用程序在运行时一次消耗的最大内存是66 MB,所以正在运行的Java程序将在其整个生命周期内保留该数量的内存,尽管它实际上是否需要66是否有MB的空间。 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? 我将所有这些告诉您,以便您可以知道如何思考以下问题: 创建和处理对象时Java如何处理内存消耗? How does this apply to my situation in particular? 这对我的情况特别适用吗?

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使用其自己的内存管理,无法使用任务管理器或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. 只要当前内存不足以处理手头的任务,并且您的内存参数(-Xmx)允许,Java就会分配内存。 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. 一旦在Java VM中释放了对象,Java进程将不会释放内存,但是VM将保留该内存以为下一个对象分配做准备。

Memory will be freed by a garbage collector. 内存将由垃圾回收器释放。 This will be triggered by events like a full memory (or a manual System.gc() call). 这将由诸如内存已满(或手动System.gc()调用)之类的事件触发。 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. 在这种情况下,免费意味着:对于新的Java对象,而不是对于底层OS。 This is the reason why you will typically see an increasing memory consumption throughout a Java execution and virtually none memory reduction. 这就是为什么您通常会在整个Java执行过程中看到内存消耗增加而几乎没有内存减少的原因。 (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) (在一种特殊情况下,当Java VM的启发式确定时,它已经分配了过多的内存,并将其返回给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. 事情变得更加复杂,因为Java VM以世代模型管理内存,旧对象和旧对象的存储区域彼此分开。 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. 至于在正在运行的VM中观察所有这些情况,我将第二次提出JVisualVM的建议(尽管我会添加,这仅对您的情况适用于Visual GC插件),但我也会将JConsole丢入圈内。 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. 由于某些我不了解的原因,Oracle删除了监视从JConsole(JVisualVM的前身)到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. 我认为,如果您不了解Java的世代内存模型及其对整体内存消耗的影响,您的学习将会失败。 As a starting point, I would suggest this article: Understanding the Java Memory Model and Garbage Collection 首先,我建议这篇文章: 了解Java内存模型和垃圾回收

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM