繁体   English   中英

Java中对象的内存消耗

[英]Memory consumption by objects in Java

我在大学开发初期就对应用程序的内存消耗有疑问。 当我启动扩展用作登录管理器的JFrame的类时,该对象将消耗大量RAM:

在此处输入图片说明

当显示此JFrame时,该程序在任何给定时间消耗大约42 MB的内存。 该JFrame允许用户登录和访问病历系统。 当用户登录时,不会简单地使登录管理器不可见。 它由.dispose()函数处理。 然后启动病历系统。

当第二个类启动时(也扩展了JFrame),该程序将消耗大量RAM:

在此处输入图片说明

在任何给定时间大约66 MB。 这是有道理的,因为此JFrame对象更大并且需要更多变量,从而导致该对象占用更多空间。 此JFrame上有一个“注销”按钮,该按钮处理病历系统JFrame对象,并在按下时创建一个新的登录管理器JFrame对象。

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

应用程序的内存消耗保持在66 MB。 当我注意到这一点时,我首先想到的是.dispose()函数可能并没有像我认为的那样真正释放分配给对象的内存。 如果是这种情况,那么随着创建越来越多的对象,反复登录和退出我的病历系统应该会不断增加我的应用程序消耗的内存量。 但是,事实并非如此。

当我登录和退出医疗记录系统时,我的应用程序的内存消耗保持在66 MB左右。 我的第二个想法是,也许是因为我的应用程序在运行时一次消耗的最大内存是66 MB,所以正在运行的Java程序将在其整个生命周期内保留该数量的内存,尽管它实际上是否需要66是否有MB的空间。 然后,如果程序需要,可以“回收”该空间并再次使用。 但是,这似乎不是最有效的处理方式。 在这种情况下,一个程序需要对数百万个元素的数组进行排序,并使用诸如合并排序之类的递归算法,该程序将占用大量空间然后将其退还给用户,在任何给定时间,程序消耗的最大空间量。 这将冻结不必要的内存量,而且似乎并非如此。

我将所有这些告诉您,以便您可以知道如何思考以下问题: 创建和处理对象时Java如何处理内存消耗? 这对我的情况特别适用吗?

正如一些建议所建议的那样,您正在寻找错误的数字。 基本上,Java使用其自己的内存管理,无法使用任务管理器或top监视您的内存消耗的起伏。

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

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

事情变得更加复杂,因为Java VM以世代模型管理内存,旧对象和旧对象的存储区域彼此分开。 对象在年轻空间中分配,并且随着每个垃圾回收而变老。 某一时刻,物体从年轻空间移到了旧空间。 这是垃圾收集效率的问题。

至于在正在运行的VM中观察所有这些情况,我将第二次提出JVisualVM的建议(尽管我会添加,这仅对您的情况适用于Visual GC插件),但我也会将JConsole丢入圈内。 由于某些我不了解的原因,Oracle删除了监视从JConsole(JVisualVM的前身)到JVisualVM的步骤区分的旧内存空间和年轻内存空间的功能。

我认为,如果您不了解Java的世代内存模型及其对整体内存消耗的影响,您的学习将会失败。 首先,我建议这篇文章: 了解Java内存模型和垃圾回收

暂无
暂无

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

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