首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中对象的内存消耗

Java中对象的内存消耗
EN

Stack Overflow用户
提问于 2017-10-05 05:37:22
回答 1查看 91关注 0票数 0

我有一个关于应用程序的内存消耗的问题,我在一所大学里处于开发的早期阶段。当我启动一个扩展作为登录管理器的JFrame的类时,对象消耗了这么多内存:

在显示此JFrame时,程序在任何给定时间消耗大约42 MB的内存。此JFrame允许用户登录和访问医疗记录系统。当用户登录时,登录管理器不仅仅是不可见的;它是用.dispose()函数处理的。然后,医疗记录系统启动。

当启动第二个类(也是扩展JFrame)时,程序消耗了这么多内存:

...roughly 66 MB在任何给定的时间。这是有意义的,因为这个JFrame对象更大,需要更多的变量,从而导致对象占用更多的空间。这个JFrame上有一个“注销”按钮,它处理医疗记录系统JFrame对象,并在按下时创建一个新的登录管理器JFrame对象。

直觉上,我会认为,由于医疗记录系统已被处理,登录管理器是运行应用程序的唯一部分,因此我的程序的内存消耗将下降到任何给定时间消耗的42 MB内存。事实并非如此。

应用程序的内存消耗仍为66 MB。当我注意到这一点时,我的第一个想法是,也许.dispose()函数并没有像我想的那样真正释放分配给对象的内存。如果是这样的话,那么当创建越来越多的对象时,反复登录和从我的医疗记录系统中登录应该会不断增加我的应用程序所消耗的内存量。然而,情况也并非如此。

当我登录或退出医疗记录系统时,我的应用程序的内存消耗保持在66 MB左右。我的第二个想法是,也许是因为我的应用程序在运行过程中一次消耗的最大内存量是66 MB,运行中的Java程序将在其生命周期内保留此内存量,而不管它是否实际需要66 MB的空间。这样,这个空间就可以被“回收利用”,如果程序需要的话,可以再次使用。然而,这似乎并不是最有效的做事方式。如果是这样的话,一个程序负责对数百万个元素数组进行排序,并使用递归算法,比如合并排序,它会占用大量的空间,然后还给它,它将被迫在任何特定时间保持程序消耗的最大空间。这会冻结不必要的内存,而且看起来不可能是这样的。

我告诉您所有这些是为了让您知道我是如何思考这些问题的:当创建和处理对象时,如何处理内存消耗?这如何特别适用于我的情况?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-15 20:47:09

正如一些人已经建议的那样,你看错了号码。基本上,Java使用自己的内存管理,不能使用任务管理器或顶层来监视内存消耗的起伏。

每当当前的内存量不足以处理手头的任务时,Java就会分配内存,并且内存参数(-Xmx)允许它这样做。一旦在Java中释放了对象,Java进程就不会释放内存,但是VM将保留该内存,以便为下一个对象分配做好准备。

内存将由垃圾收集器释放。这将由诸如完整内存(或手动System.gc()调用)等事件触发。垃圾收集器将识别所有无法到达的对象,并释放它们消耗的空间。在这种情况下,免费意味着:对于新的Java对象,而不是底层操作系统。这就是为什么在Java执行过程中,您通常会看到内存消耗增加,而内存几乎没有减少的原因。(有一种特殊情况,当Java的启发式确定时,它已经分配了太多的内存并将其返回到操作系统)

事情仍然更复杂,因为Java在一个分代模型中管理内存,内存区域为新旧对象彼此分离。对象在年轻的空间中分配,并随着每次垃圾收集而变老。在某种程度上,物体会从年轻的空间移动到旧的空间。这是一个垃圾收集效率的问题。

至于在运行中的VM中观察所有这些情况,我将支持JVisualVM的建议(尽管我要补充一句,它只适用于Visual插件),但我也会将JConsole抛到脑后。出于某些原因,我不明白,Oracle删除了监视从JConsole ( JVisualVM的前身)到JVisualVM的步骤中区分的新旧内存空间的功能。

我认为,如果您不理解Java的分代记忆模型及其对整体内存消耗的影响,您的研究就会失败。作为起点,我建议这篇文章:理解Java内存模型和垃圾收集

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46578545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档