前言:
我们在面试时经常会遇到String相关的题,小编刚开始时也是云里雾里,每次都是分析半天最后还是半猜半赌的 选一个,今天我们就来从jvm内存的角度分析下这个问题。
Jvm简介
Jvm是虚拟机的英文简称。它是java运行环境的一部分,是一个虚构出来的计算机,它是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
那么java程序是怎么执行的?
如图所示,.java文件在执行时会先被编译为.class文件即二进制文件,然后再在jvm中执行,那么jvm是如何执行的?要想了解这些就必须了解jvm的内存模型
Jvm内存模型
vm内存模型分为线程私有和线程共享两个区域,从上面的模型图可以看到堆和方法区是公共部分,而其它的是线程私有,那么各个部分到底有些什么?
我们以上面这段代码结合画图来说明一下,
如图所示:
堆区
存储的全部是对象,每个对象都包含了一个与之对应的信息。
jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(即我们常说的地址值),而对象实体都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和方法体。
方法区中包含的都是在整个程序中永远唯一的元素,如class,静态变量。
通过上面的分析我们再来分析一下最开始的题目,画出它对应的内存模型图
从内存模型图中可以清楚的得出结论s1,s2,s3都不相等
在最后简单介绍下jvm内存模型
java 栈:线程私有,生命周期和线程,每个方法在执行的同时都会创建一个 栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。方法的执行就对应着栈帧在虚拟机栈中入栈和出栈的过程;栈里面存放着各种基本数据类型和对象的引用;
本地方法栈:本地方法栈保存的是native方法的信息,当一个JVM创建的线程调用native方法后,JVM不再为其在虚拟机栈中创建栈帧,JVM只是简单地动态链接并直接调用native方法;
堆:Java堆是程序员需要重点关注的一块区域,因为会涉及到内存的分配调优(new关键字,反射等)与回收(回收算法,收集器等),这些我们以后再说;
方法区:也叫永久区,用于存储已经被虚拟机加载的类信息,常量("zdy","123"等),静态变量(static变量)等数据。
程序计数器:一块较小的内存空间,当前线程执行的字节码的行号指示器;各个线程之间相互独立存储,互不干涉;
运行时常量池:运行时常量池是方法区的一部分,用于存放编译期生成的各种字符串(如"zdy","123"等)、静态变量和符号引用。