java中的堆,栈,静态域,常量池

时间:2022-12-27 08:11:18

Java内存分配主要包括以下几个区域:

  1. 寄存器:我们在程序中无法控制

  2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中

  3. 堆:存放用new产生的数据

  4. 静态域:存放在对象中用static定义的静态成员

  5. 常量池:存放常量

  6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间

Java内存分配中的栈

栈中主要存放两种数据类型:

  1. 在函数中定义的一些基本类型的变量数据,也就是局部变量。
  2. 对象的引用变量。

    当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 (请注意堆和栈的垃圾回收机制
    栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。
    栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

Java内存分配中的堆

堆内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态 分配内存,存取速度较慢。
在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。
实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!

Java内存分配中的常量池

常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:

类和接口的全限定名;
字段的名称和描述符;
方法和名称和描述符。

这里需要注意,在java中什么叫做常量。你一定是觉得int a = 1 ;1是常量对吗?生活中可以这么理解,但java中就不是了,1 只是代表一个值,所谓的常量在java中是指final修饰的变量,它们是不可改变的,也就是初始化后就再也无法改变,这样才叫做常量

Java内存分配中的静态域

Java 中被static 修饰的域或方法常被称作静态的。
如果将静态域定义为static ,那么每个类中只有一个这样的域,而每一个对象对于所有的实例域都有自己的一份拷贝本。例如,学生类中有一个实例域studentId和一个静态域nextId, 如下所示:

class Student{  
private static int nextId = 1;
private String studentId;
......
}

那么,每一个学生对象,都会有自己的studentId, 但是这个类的所以对象将共享一个nextId域, 换句话说就是: 如果有100个Student类对象 ,那么有100个实例域studentId,每一个student都有自己的一份,但是只有一个静态域nextId , 100个学生对象共享这一个静态域nextId, 使没有学生对象,静态域也是存在的,它是属于类的,而不是属于任何独立的对象。静态域(静态方法)可以直接用类名来调用,而不用创建对象用对象来调用(在绝大多数的面向对象的语言中,静态域被称作为类域。