Java 数据存储

寄存器register

最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制

  • 最快的存储区(由编译器根据需求分配,无法从程序中控制)
  • 位于处理器内部
  • 数量有限

常量存储constant storage

存放字符串常量和基本类型常量(public static final)

  • 常量值通常直接存放在程序代码内部
  • 有时在嵌入式系统中,常量本身会和其他部分分割离开,所以在这种情况下,可以选择将其放在ROM中 (ROM,Read Only Memory,只读内存。一种只能读出事先所存数据的固态半导体存储器,它相当于PC机上的硬盘,用来存储和保存数据。RAM和ROM相比,两者的最大区别是RAM在断电以后保存在上面的数据会自动消失,而ROM就不会。)

静态存储区static storage

存放静态成员(static定义的)包括静态成员变量和静态成员方法(类方法)
  • 静态是指“在固定的位置”
  • 静态存储里存放程序运行时一直存在的数据
  • 可用关键字static来标识一个对象的特定元素是静态的
  • 但JAVA对象本身从来不会存放在静态存储空间里

重点注意:

  1. 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员。如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。
  2. 在普通成员方法中,则可以直接访问同类的非静态变量和静态变量。
  3. 静态方法中不能直接调用非静态方法,需要通过对象来访问非静态方法。

栈stack

存放基本类型的变量数据和对象,数组的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中)

  • 速度仅次于寄存器

  • 通过它的“栈指针”从处理器获得支持;
  • 栈指针向下移动,分配新内存;向上,释放内存;
  • 这一约束限制了程序的灵活性:创建程序时,JAVA编译器必须知道存储在栈内所有数据的确切大小和生命周期,生成相应代码,以便上下移动栈指针;因此某些JAVA数据存储在栈中,而JAVA对象不存储在其中,位于通用RAM中 (RAM,random access memory随机存取存储器),与CPU直接交换数据的内部存储器,也叫主存(内存)。随时读写,速度很快,通常作为临时数据存储媒介)

特点

函数中定义的基本类型变量,对象的引用变量都在函数的栈内存中分配。

栈内存特点,数数据一执行完毕,变量会立即释放,节约内存空间。

栈内存中的数据,没有默认初始化值,需要手动设置。

堆heap

存放所有new出来的对象

  • 位于通用RAM中,用来存放所有的JAVA对象
  • 不同于栈的好处:不需要知道存储数据分配多少区域以及生命周期,有很大的灵活性
  • 需要创建一个对象时,只需new一行代码,执行这行代码,会自动在堆里进行存储分配
  • 为这种灵活性付出相应代码,用堆进行存储分配比用栈进行存储需要更多的时间

特点

堆内存用来存放new创建的对象和数组。

堆内存中所有的实体都有内存地址值。

堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。

堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)。

运行时数据区包括:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器

虚拟机栈区(栈区)

也就是我们常说的栈区,线程私有,存放基本类型,对象的引用和returnAddress,在编译期间完成分配。

堆区

JAVA堆,也称GC堆,所有线程共享,存放对象的实例和数组,JAVA堆是垃圾收集器管理的主要区域。

方法区

所有线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。

程序计数器

线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址。

本地方法栈(Native Method Stacks)

与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

特点

堆内存用来存放new创建的对象和数组。

堆内存中所有的实体都有内存地址值。

堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。

堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)。