这篇博客我们主要讲述的是运行时数据区的这5个,其中画了斜杠的代表所有线程共享的,没有画斜杠的代表线程隔离得到数据区
我对程序计数器的理解就是
1.每个线程都有独自的程序计数器
2.基础的一些功能靠它来进行实现
《Java虚拟机》中的解释是:字节码解释器工作就是通过改变计数器中的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支,循环,跳转,异常处理,线程恢复等基础功能都需要这个计数器
每条线程都有独自的程序计数器,且每个程序计数器互不影响,独立存储
如果执行的是一个java方法,程序计数器记录的是正在执行的虚拟机字节码指令的地址,如果是本地方法,计数器为空
Java虚拟机地址也是线程私有的,这个又经常被叫做栈内存,
一般
都被存在了Java虚拟机栈
它的生命周期与线程相同,每个方法执行的时候,Java虚拟机都会同步创建一个栈顶,一个方法从执行到执行完毕就对应着一个栈顶在虚拟机栈中从入栈到出栈
比如
String a = new String("你好");
这里面a就被存在虚拟机栈
它和java虚拟机栈差不多,只不过虚拟机栈执行的是java方法服务,本地方法栈则执行虚拟机使用的本地方法服务
通常保存在动态链接库(.dll/.so文件)
这就是我们一般说的堆内存
它是所有线程所共有的,
还是举刚才的那个例子
String a = new String("你好");
那么这里面是什么保存在堆内存里面呢?
是String里面的你好
作为虚拟机中所管理的内存最大的地方,java堆只存放对象实例
虽然Java的堆是所有线程共有的,但是有时为了提高运行时的效率,所有线程共有的Java堆可以划分多个线程私有的分配缓存区,虽然是私有了,但是仍然存放的是对象实例
方法区也是多个线程可以公共访问的内存区域
它可以存储
等等
运行时常量池是方法区的一部分,所以它也是多个线程可以公共访问的内存区域
比如下面这段代码
String a = "2";
其中2就存放在运行时常量池里面
所以现在我们看一下这两段代码
String a = "2";
String b = new String("2");
这时候我们写
System.out.println(a==b);
最后输出的是false
这是因为第一个2是存放在常量区,但是第二个2是存放在Java堆里面的
存放的地址的位置不一样,虽然value不一样,但是因为地址不同,所以最后返回false
但是
如果你用
String c = b.intern();
调用这个方法之后原本存放在Java堆里面的2存放在了常量区
这时候再调用
System.out.println(a==c);
这时候就返回了true
它是堆外内存,不受Java堆大小的限制,而是受总内存大小的限制,通过直接内存可以提高性能与效率,避免了在Java堆和本地堆复制数据