课时4:对象内存分析

简介: 接下来对对象实例化操作展开初步分析。在整个课程学习中,对象使用环节往往是最棘手的问题所在。

课时4:对象内存分析

 

摘要:接下来对对象实例化操作展开初步分析。在整个课程学习中,对象使用环节往往是最棘手的问题所在。

 

因为在Java里,类属于引用数据类型,引用数据类型的最大难点在于需进行内存管理,且在执行相关操作时,内存关系会随之发生变化。此次针对之前程序中的内存关系做简要分析,鉴于完整分析过程颇为繁杂,先进行简单剖析。


以如下程序作为主要分析对象,即程序中创建实例化对象,进而进行属性设置以及方法调用的操作。

public class JavaDemo{ 
public static void main(String args[]){
Person per=new Person();//声明并实例化对象
 per.name="张三"; 
 per.age=18;
per.tell(); //进行方法的调用

进行内存分析时,先给出两块基础的内存空间,分别是堆内存和栈内存。在学习方法递归时,曾接触过“Stack Overflow”(栈溢出)这一概念,其涉及栈出现的问题,且与后续要深入解释的栈相关联。


堆内存保存的是对象的具体信息。例如,有个人叫王建,说“王建干活”,干活的是王建这个人本身;说“王建去死”,也是这个人本身面临相应情况,王建是真实存在的实体,即便其改名,本质上还是那个人去干活。所以,堆内存用于存放对象具体信息。


栈内存类似整形变量,保存的是一块堆内存的地址,通过该地址能找到堆内存,进而获取对象的具体内容。


需注意,此概念后续还会深入分析,先建立基本印象即可。所有堆内存地址都有相应的地址编号,不同堆内存的编号不同。栈内存在整个处理过程中,其内容与对象信息相关,后续会围绕此进一步深入探讨。

image.png

在整个实际开发过程中,要进行对象真实且完整操作信息的保存。需明确,栈内存中实际存放的是对应内存块的地址数据,通过该地址能够找到对应的堆内存,进而借助堆内存开展完整的操作。


在此有个关键要点需牢记,在程序里,堆内存空间的开辟是通过“new”关键字来完成的。在整个项目中,“new”是内存分析里既令人头疼又极为重要的关键字。明确二者关系后,来看后续如何进一步处理。


在清楚上述对应关系后,针对之前的程序展开分析。为此,通过画图来梳理逻辑,一步步呈现出来。鉴于后续预计会进行诸多内存分析,需做好相应心理准备。

public class JavaDemo{ 
public static void main(String args[]){
Person per=new Person();//声明并实例化对象
 per.name="张三"; 
 per.age=18;
per.tell(); //进行方法的调用

回到代码中,首先明确堆内存与栈内存的关系。第一点,堆内存依靠“new”来开辟。很清晰的是,当程序中出现“new”这个关键字时,基本就能确定对于当前程序而言,要在此处开辟一个堆内存空间,将其称作“开辟新的堆内存”。在Java中,“new”属于内存开辟的最高级别语句,如同拥有绝对权威,任何情况下只要出现“new”就必须开辟内存空间。


第二个问题,堆内存存放的是具体的数据。以“Person”为例,“Person”中有哪些数据呢?有两个,一是“name”,二是“age”。若代码中未给“name”赋值,其值为空;“age”的值为0。由此可得出结论,在定义保存时,在相应内存里就存有“name”和“age”这两个数据。


并且,所有的堆内存都有对应的物理内存地址,这是必然存在的。确定好这些语句相关内容后,再来探讨“new Person”这个操作能实现什么功能,以“Person”的本质来讲,其在整个代码中实际定义了什么内容。通过画图来进一步呈现,这是堆内存中保存的具体数据,前面已对此进行过分析。


然而,当下的问题在于为何要存储这些数据,是由类来定义这些数据的,其实就是person。

image.png

通过画图进一步阐释,因这部分内容很关键。在整个程序代码里,“new Person”直接决定了程序中要保存的数据内容。若换用其他类,比如“Dog”类,里面存储的就是与“Dog”相关的数据,二者互不相关。

image.png

至此,对程序的第一波分析已完成,程序按从左到右的顺序执行,这部分代码确定好后,接下来要考虑右边的内容,即栈内存。


已知栈内存应存放堆内存的地址,不过在这个程序中,发现其在栈内存里存了与“Person”相关的内容。正常而言,此处应存放地址,因只有通过地址才能引用对应的堆内存空间。为便于分析简化,可简单理解为对象的名称保存在了栈内存之中,这是一种简化理解方式。


要知道对象是程序中的元素,虽说此处告知有个“p”,其本应存放的是地址,但可简化理解为“p”描述的是栈内存中保存的一个名字。


如此,整个过程得以区分开。从整体的访问结构来看,能够得出相应的内存分析图,应能明白其中意思。这里存在引用关系,整个过程涉及到了栈内存,这便是第一行语句执行后呈现的效果。

image.png

接下来看第二个语句,即“per.name=张三”。若出现这样的语句,问题就比较清晰了。将相关代码复制出来放置在此处,之前的第一个图稍显复杂,第二个图恢复正常设计,不然不好描述。

来看“per.name”,严格来讲,“per”描述的是一个栈内存地址。而“per.name”指的是该地址所对应堆内存中的“name”属性。


所以此时意味着要将堆内存中的“name”赋值为“张三”。

同样地,对于代码“p.age=18”,这相当于把堆内存中的数据进行了改变,最终输出的结果就是“张三18”。若不信,可再次运行代码验证,确实会输出“张三18”,如此便完成了最基础的内存分析处理。

image.png

对于对象实例化,之前已分析过,有两种语法。一种是之前使用过的声明并实例化对象,另一种是分步完成操作。


下面针对分步的内存操作进行分析,来看操作代码,定义程序代码如下:

image.png

public class JavaDemo{ 
public static void main(String args[]){
Person per=new Person();//声明并实例化对象
 per.name="张三"; 
 per.age=18;
per.tell(); //进行方法的调用
Person per=null;声明化对象
per.=new Person();实例化对象

第一个步骤称作声明对象,第二个步骤称作实例化对象,现在是分步操作,与之前的区别在于不是一步完成,而是分两步进行。不过结果是一样的,毕竟最终都得到了对象。那这两步具体是如何进行的呢?下面通过内存分析来梳理操作过程。


我们现在回到这个程序继续进行内存分析。

首先来看第一句“Person per=null;”,当出现“per=null”时,要知道,程序中堆内存和栈内存是始终需要关注的,这是关键所在。此时给了“null”,这里并没有“new”关键字,那就表明只是开辟了一个栈内存空间,并没有具体的指向。

image.png

而当执行第二句语法“per=new Person();”时,之前讲过,只要看到“new”关键字,不用思考,它肯定是用来开辟空间的,这几乎是一种条件反射了。一旦开辟空间,属性都是默认值,像这里的“name”默认是空值,不过千万不要忘记,在内存分析中,内存都是有地址的。


实际上这里一旦使用“new”开辟了新空间,这个新空间的值也一定会有一个地址保存在栈内存中,大家应该能明白这个意思吧。后续的赋值操作,和之前讲的那种情况并没有本质区别,最终输出的结果肯定是姓名为“张三”,年龄为“18”,这就形成了分步处理,这样就能看出两种操作方式的差别了。


但需要特别注意的一点是,所有的对象在调用类中的属性或方法时,必须要在实例化完成之后才可以执行。下面把错误代码展示出来,大家看一下,在整个代码中,

per.name="张三"; 
 per.age=18;
per.tell(); //进行方法的调用

只是声明了对象,并没有对对象进行实例化,所以此时是无法调用属性或方法的。关键在于,我们要清楚这种无法调用所带来的问题是什么。


对代码进行编译并再次执行,会出现两个问题。

1.Exception in thread"main"java lang NullPointer Exception

2.favaDemo.java:IH


在Java代码中,查看第11行per.name=null,这里存在没有对对象进行实例化就使用的情况。我们说这时就会出错,随后,程序中出现的“NullPointerException”(空指针异常),明确描述的就是一种空指向异常。


也就是说,在没有对对象进行实例化,也就是没有在堆内存开辟相应空间时,就会产生这样的问题,并且只有引用数据类型才会存在此类问题。比如在后续的开发过程中,“NullPointerException”会一直伴随着开发工作,同时一定要牢记,只有引用数据类型会出现“NullPointerException”,而基本数据类型是不存在这类问题的,因为基本数据类型本身就是实际的数值。


所以说,这是一个基础的内存分析结构,大家一定要清楚这个结构,以后切记一点,对象必须在实例化之后才能够使用,否则是无法使用的。

相关文章
|
12月前
|
Web App开发 监控 JavaScript
监控和分析 JavaScript 内存使用情况
【10月更文挑战第30天】通过使用上述的浏览器开发者工具、性能分析工具和内存泄漏检测工具,可以有效地监控和分析JavaScript内存使用情况,及时发现和解决内存泄漏、过度内存消耗等问题,从而提高JavaScript应用程序的性能和稳定性。在实际开发中,可以根据具体的需求和场景选择合适的工具和方法来进行内存监控和分析。
|
5月前
|
存储 弹性计算 缓存
阿里云服务器ECS经济型、通用算力、计算型、通用和内存型选购指南及使用场景分析
本文详细解析阿里云ECS服务器的经济型、通用算力型、计算型、通用型和内存型实例的区别及适用场景,涵盖性能特点、配置比例与实际应用,助你根据业务需求精准选型,提升资源利用率并降低成本。
387 3
|
28天前
|
设计模式 缓存 Java
【JUC】(4)从JMM内存模型的角度来分析CAS并发性问题
本篇文章将从JMM内存模型的角度来分析CAS并发性问题; 内容包含:介绍JMM、CAS、balking犹豫模式、二次检查锁、指令重排问题
64 1
|
4月前
|
存储 人工智能 自然语言处理
AI代理内存消耗过大?9种优化策略对比分析
在AI代理系统中,多代理协作虽能提升整体准确性,但真正决定性能的关键因素之一是**内存管理**。随着对话深度和长度的增加,内存消耗呈指数级增长,主要源于历史上下文、工具调用记录、数据库查询结果等组件的持续积累。本文深入探讨了从基础到高级的九种内存优化技术,涵盖顺序存储、滑动窗口、摘要型内存、基于检索的系统、内存增强变换器、分层优化、图形化记忆网络、压缩整合策略以及类操作系统内存管理。通过统一框架下的代码实现与性能评估,分析了每种技术的适用场景与局限性,为构建高效、可扩展的AI代理系统提供了系统性的优化路径和技术参考。
210 4
AI代理内存消耗过大?9种优化策略对比分析
|
8月前
|
Java 编译器 Go
go的内存逃逸分析
内存逃逸分析是Go编译器在编译期间根据变量的类型和作用域,确定变量分配在堆上还是栈上的过程。如果变量需要分配在堆上,则称作内存逃逸。Go语言有自动内存管理(GC),开发者无需手动释放内存,但编译器需准确分配内存以优化性能。常见的内存逃逸场景包括返回局部变量的指针、使用`interface{}`动态类型、栈空间不足和闭包等。内存逃逸会影响性能,因为操作堆比栈慢,且增加GC压力。合理使用内存逃逸分析工具(如`-gcflags=-m`)有助于编写高效代码。
151 2
|
12月前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
364 62
|
11月前
|
缓存 监控 算法
Python内存管理:掌握对象的生命周期与垃圾回收机制####
本文深入探讨了Python中的内存管理机制,特别是对象的生命周期和垃圾回收过程。通过理解引用计数、标记-清除及分代收集等核心概念,帮助开发者优化程序性能,避免内存泄漏。 ####
244 3
|
12月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
346 1
|
12月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
201 5
|
12月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
578 4

热门文章

最新文章