目录

1.程序计数器:

2.虚拟机栈(java栈)

3.本地方法栈

4.堆

5.方法区

      5.1运行时常量池

6.举例说明


Java和C++有一堵由内存分配和垃圾回收技术围成的墙,里面的人想出去,外面的人想进去。

Java虚拟机执行程序时会把所管理的内存分为若干不同的区域,其总称为运行时数据区域。如下:

java是存储地址 java存储区_字面量

1.程序计数器:

    当前线程执行所执行的行数指示器,每个线程独有的区域。也就是记录当前线程执行的代码执行到了哪个地方。是唯一不会发生OutOfMemoryError的区域。

2.虚拟机栈(java栈)

   线程私有的区域,或叫做局部变量表部分,存放各种编译器可知的基本数据类型(8大基本数据类型)、对象引用(Dog dog =new Dog();存放Dog类的引用dog)。因为基本数据类型的程度是已知的,对象引用存储的是地址,因此表所需的内存在编译时就已经确定。64位的long和short占2个局部变量空间,其他基本类型占一个。

3.本地方法栈

   本地方法栈和虚拟机栈的功能类似,只是虚拟机栈为执行java方法服务,本地方法栈为Native方法服务。在我们当前的java虚拟机,即HotSpot虚拟机,这两个区域被合二为一了。

4.堆

   堆是内存中最大的一块,为所有的线程共享。唯一目的是存储对象实例,是垃圾回收器管理的主要区域。

5.方法区

  各线程共享,存储已被加载的类信息(类名、访问修饰符、方法描述等)、常量、静态变量等,官方中也叫非堆,可能是为了和堆区分开来。

      5.1运行时常量池

           运行时常量池是方法区的一个部分,存放编译期生成的各种字面量和符号引用。

            扩充:字面量和符号引用。字面量可以理解为在赋值时的右值,不管是int a =5 ;String b ="abc",只要赋值时的右值为具体的值,其就为字面量。符号引用:和对象引用区分开来,对象引用是对对象的标识,符号引用是对在编译期间符号的标识,比如说我引入了一个java.lang.util包,编译时就会产生一个对java.lang.util的标识,用一个符号来替换它,以便在后续能找到它。

6.举例说明

  看了上面的介绍,对各个区域有大概的了解,下面举一个简单的例子说明:

class Example{
  
   int  a = 5;
   String b ="hello";
   static int x = 5;
   final String y ="hello";
   String str = new String("world");

 

}

字面量有: 5   hello      基本类型变量: a   b   对象引用: str  静态变量: x   常量 :y.

最终存储区域:

栈: a  b   str 分别指向了存储值的地址

堆: String对象实例 值为 world

方法区: Example类的信息(包括了哪些变量、哪些引用),5   hello   y

world不存在方法区中,这也就解释了String 包装类和String做 == 比较时,返回为false的 原因,一个是值,一个是引用,需要用.eques()来比较