1.上节回顾
2.内存管理



在程序中,无论是代码还是数据都要保存在内存中,而内存变化由运行程序的JVM来管理所需的内存空间。内存又分为三大块,分别是堆(heap)、栈、方法区。
2.1 堆内存
堆:可以理解为内存中一片分散的区域
堆内存在某种意义上来说是在内存中最灵活的,也是唯一可以让程序员主动控制的空间。因为堆内存里面存放的都是new出来的对象实例,用完之后靠垃圾回收器不定期的自动消除比如:
Human h1 = new Human();
程序运行的时候会先执行等号右边的new Human();在内存中创建出一个h1对象,假设里面有两个属性,名字和年龄,地址为0x50;
其实h1对象就是创建在堆内存中的,每new一次,就会开辟一块内存空间,而且每个对象都会有唯一的内存地址。
由于每个对象都没有名字,只有地址,由引用变量保存,指向对象地址,大家先记住用来保存地址的引用变量是保存在栈中。

2.1.1. 对象生命周期
对象也是有生命周期的,当一个对象没有任何变量指向他的时候,就会被视为废弃的对象,就要等待被回收。对象中的成员变量也会等待回收。
所以对象和成员变量的的生命周期为:从对象在堆中被创建开始到对象从堆中被回收结束。
2.1.2 垃圾回收机制
在Java中会有一个自动回收的机制:叫垃圾回收器(Garbage Collection),简称gc,他是JVM自带的一个线程(自动运行着的程序),用于回收没有任何引用指向的对象。
问题一:
既然gc会把废弃的对象自动回收掉,那会不会把成员变量也一并回收了?
2.1.3 内存泄漏
内存泄漏就是指不再使用的内存没有被及时的回收掉。严重的内存泄漏会因为过多的内存占用而导致程序奔溃。
例如:
Human h1 = new Human()Human ();
new出来的对象都存储在堆中,然后通过引用变量保存地址指向h1对象,假如有另一个
Human h2 = h1

问题二:
那么h2会不会新开辟一个空间?
问题三:
如果这时候h1=null的时候意味着c里面已经没有地址了,那对象算不算垃圾?
2.1.4.System.gc()方法
而gc的回收过程对于程序员来说是透明的,不一定说是发现了垃圾就会立马清除掉,所以呢这时候就需要程序员手动调用System.gc()方法来建议JVM尽快帮我们调用gc来回收垃圾。
2.2.栈内存
栈:可以理解为是内存中一片连续的区域
基本数据类型,局部变量都是存放在栈内存中,用完就消失。
JVM在其内存空间开辟一个称为”栈”的存储空间,用于存储程序运行时在方法中声明的所有的局部变量
方法中的变量就是局部变量,是在栈内存中分配的,如果变量为基本类型,则在栈内存储的是该变量的值。如果变量为引用类型,则在栈中存储的是堆中的对象的地址。
一个运行的Java程序从开始到结束可能会有多次方法的调用,而JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为是该方法的栈帧。而且一个栈帧对应一个正在调用中的方法,栈帧里面存放了这个方法的局部变量和参数。只有当方法调用完了,对应的栈帧也将会被清除,局部变量也随之失效。
例如:
class Add{
int numA;
void show(int numB){
int numC = 5;
}
}
2.2.1.局部变量的生命周期
方法调用时,生命周期开始,方法结束调用后,生命周期结束
2.2.2.成员变量和局部变量
写在类中,方法外的叫成员变量,有默认的初始值,而且在类实例化的时候,存放在堆中,和对象的生命周期一样,对象失效时,成员变量也一并失效。
class Add{
int numA;
}
写在方法里面的,包括参数都叫做局部变量,没有默认的初始值,必须自己设定初始值,方法被调用时,存在栈中,方法调用完了,就从栈中清除了。
2.3.方法区
方法区是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
方法只有一份,通过this来区分具体的对象,谁调用就用this
标签: