JAVA(三)对象内存管理

本文详细介绍了Java中的对象内存管理,包括堆、栈和方法区的划分。对象在堆中分配,成员变量与局部变量的生命周期,以及垃圾回收机制的工作原理。强调了及时释放引用以利于垃圾回收的重要性,并解释了System.gc()方法的作用。同时,阐述了方法区存储类信息的功能,指出方法在所有对象间共享。最后,讨论了成员变量与局部变量的区别。
摘要由CSDN通过智能技术生成

对象内存管理

对象内存管理

在Java中,有Java程序、虚拟机、操作系统三个层面。其中Java程序与虚拟机交互,虚拟机与操作系统交互。编译好的Java字节码文件运行在JVM上。

JVM会将申请的内存从逻辑上划分为三个区域:堆、栈、方法区。

堆内存

对象存储在堆中

JVM在其内存空间开辟了一个称之为“堆”的存储空间,这部分空间用于存放new关键字创建出来的对象。

  • 看如下代码:
Cell c = new Cell();

从图中可以看到右侧的堆内存,new Cell() 所创建的对象在堆中分配,同时成员变量也在此分配,并赋予初始值为零。引用类型变量 c 在栈内存中分配,其中保存的数据,为对象在堆内存中的地址信息,假设对象在堆内存的地址为00DF(十六进制),则 c 中保存的即是00DF。

成员变量的生命周期

当生声明好对象后,对该对象(堆中的Cell)的访问需要依靠引用变量(栈中的c)那么当一个对象没有任何引用时该对象就被视为废弃的对象,属于被回收的范围,同时对象中的所有成员变量也随之被回收。

  • 成员变量的生命周期

    对象在堆中创建开始到对象从堆中被回收结束。

  • 以下代码演示了对象不再被引用

Cell c = new Cell();
c = null;

当将c赋值为null时,表示c不再指向刚刚分配的对象空间,此时成员变量失效。

垃圾回收机制

垃圾回收器Garbage Collection,GC)是JVW自带的一个线程(自动运行的程序)用于回收没有任何引用指向的对象。

  • 工作原理

    GC线程会从栈中的引用变量开始跟踪,从而判断哪些内存是正在使用的,若GC无法跟踪到某一块堆内存,那么GC就认为这块的内存不再使用了,即为可回收。

Java程序员不用担心内存管理,因为GC会自动管理。

Java程序的内存泄露问题

内存泄漏是指,不再被使用的内存没有被及时的回收,严重的内存泄漏会因为过多的内存占用而导致程序的崩溃。在程序中应当尽量避免不必要的内存浪费。

GC线程判断对象是否可以被回收的依据是该对象是否有引用来指向,因此,当确定该对象不再被使用时,应当及时将其引用设为null,这样,该对象即不再被引用,属于可回收的范围。

System.gc()方法

GC是定时或定期才自动回收垃圾的, 如果需要GC即刻回收无用对象时,可以调用System.gc()方法。此方法用于JVM马上调用GC回收资源。

栈内存

栈存放方法中的局部变量

JVM在其空间开辟了一个称之为“栈”的存储空间。这部分空间用于存放程序运行时在方法中声明的所有局部变量。

  • 看如下代码:
Cell c = new Cell();
int num = 5

说明:方法中的变量即为全局变量,是在栈内存中分配,若变量为值类型,则在栈中存储的就是该变量的值,若变量为引用类型,则在栈中存储的是对中对象的地址。

局部变量的生命周期

一个运行的Java程序从开始到结束会有很多方法的调用,JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称之为该方法的栈帧。一个栈帧对应一个正在调用的方法,栈帧中**存储了该方法的参数、局部变量等数据。**当某一个方法调用完成后,其对应的栈帧清除,局部变量即失效。

成员变量和局部变量

成员变量与局部变量的差别如下:

  • 局部变量
    1. 定义在方法中
    2. 没有默认值,必须自行设定初始值
    3. 方法被调用时,存在栈中,方法调用结束时局部变量从栈中被清除
  • 成员变量
    1. 定义在类中,方法外
    2. 由系统设定默认初始值,可以不显式初始化
    3. 所在类被实例化后,存在堆中,对象被回收时,成员变量失效

方法区

方法区存放类的信息

方法区用于存放类的信息,Java程序运行时,首先会通过类装载器载入类的字节码文件,经过解析后将其装入方法区,类的各类信息(方法)都在方法区存储。

  • 看如下代码:
Cell c = new Cell();

程序在执行这句话时,Cell类首先被装载到JVM的方法区,其中包括类的基本信息和方法定义等。如下图:

通过图可以看出,在方法区中,包含Cell类的字节码文件,及类的基本信息及方法drop等。

方法只有一份

当类的信息被加载到方法区时,除了类的信息以外,同时类的方法定义也被加载到方法区。

类在实例化对象时,多个对象会拥有各自在堆中的空间,但所有实例对象是**共用方法区中的一份方法。**意味着方法只有一份。

  • 看如下代码:
JFrame f1 = new JFrame();
JFrame f2 = new JFrame();
f1.setSize(200,300);
f2.setSize(300,400);

如上的代码中,对象有两个,但是setSize方法只有一份,分别针对f1指向的对象和f2指向的对象调用了两次。

 


❤️ END ❤️
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JOEL-T99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值