本文大部分内容来源于《深入JAVA虚拟机》

java笔试题中,出现频率较高的一道题:String str = new String("str");String str2 = "str";产生了几个对象,这道题解释起来比较费劲,咱们从根源说起先。

1、虚拟机内存模型

java string申请大内存 java string内存模型_方法区

人们常说jvm分为堆区和栈区,这是比较粗的分发,实际的情况参照上图。和本道面试题有关的区域有:虚机栈、堆区、方法区、运行时常量池。

虚拟机栈:

这就是大家常说的栈区。是现成私有的,生命周期和线程相同。虚拟机栈描述的是java方法执行的内存模型:方法执行时同时创建一个栈帧(stack frame)用于存储局部变量表、操作栈、动态链接、方法出口。方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈道出栈的过程。

堆区:

此区域的唯一功能就是存放对象实例。几乎所有的对象实例都是在这里分配的。虚拟机规范中的描述:所有的对象实例和数组都要在堆上分配。但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术导致了一些微妙的变化,所有的对象都分配在堆上也逐渐变得不是那么“绝对”的了。

方法区:

存储一杯jvm加载的类信息、常量、静态变量、即时编译器编译后的代码数据

运行时常量池:

运行时常量池(Runtime Constant Pool)是防范去的一部分


2、到底产生几个对象

看String str = new String("str"),String str这部分将反映到java栈的本地变量表中作为一个refrence,而new String("str")将会在堆区分配内存,同时检查该实例的值("str")是否存在运行时常量池,不存在则在运行时常量池创建该值。

java string申请大内存 java string内存模型_java string 几个对象_02


再看接下来的这句String str2 = "str",String str2在栈区创建一个refrence,没有new,也就是没有对象实例在堆区分配,而在运行时常量池中存在"str",则无需创建新的值

java string申请大内存 java string内存模型_堆区_03



返回来再看这两句到底创建的多少东西,在栈区2个 reference、堆区一个String的实例、方法区内运行时常量池中一个字串值"str"。很遗憾,这些东西里面没有一样是称作为“对象”的,所以说这两句共创建了0个对象。卧槽,0个对象是啥意思,意思就是说:出笔试题的人太挫了,基本概念都搞不懂,瞎出题,害的做题人看不懂题。

哈,开个玩笑,真的做题的时候,可别写0个对象,可是我真的不知道该回答几个



java string申请大内存 java string内存模型_常量池_04

class='magplus' title='点击查看原始大小图片' />

大小: 64.1 KB


java string申请大内存 java string内存模型_常量池_05

大小: 53.9 KB


java string申请大内存 java string内存模型_方法区_06

大小: 41.7 KB

查看图片附件