请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于String、常量池的问题

String s1 = new String(“aaa”);

在内存中的创建过程为:

  1. 首先在栈内存中为s1分配一块空间。
  2. 在堆内存中为String对象分配一块空间,并赋初值。
  3. 执行方法(成员变量赋值、构造代码块共同收敛得到的函数)。
  4. 调用构造方法
  5. 讲String对象在内存中的地址赋值给栈中的 s1。

正常对象的创建过程应该是这样的。

我想请问,"aaa"放到了字符串的常量池了吗?它是什么时候被放进常量池的?

我搜索了一下大概的答案都是编译时就确定了,但是编译的时候也没有jvm运行时内存什么事呀。

我的理解:是不是加载的时候时候类加载器将字面量和符号符号引用放入了堆,其它类信息放入方法区,所以"aa"是在类生命周期的加载阶段变放入了常量池,我这样理解对吗?

但是加载在验证的前面呀?没有验证他怎么放进去,怎么放的对。

正在回答

2回答

翔仔 2019-03-03 12:09:11

为解释清楚些,先说三个定义,

首先是字符串常量池,在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享;

其次是Class常量池,我们写的每一个Java类被编译后,就会形成一份class文件;class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量和符号引用;

字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;

符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

第三个是运行时常量池,运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本,不同之处是:它的字面量可以动态的添加(String#intern()),符号引用可以被解析为直接引用。

JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。

贴出这么多概念主要是先把编译时和运行时分开,编译的时候会创建出字符串常量池;

具体在第一次引用该项的 ldc 指令被第一次执行到的时候。 解析 CONSTANT_String 时(该代码也就是执行到 Strings = "hello"; 的时候),根据 index 去运行时常量池查找 CONSTANT_UTF8,然后找到对应的 Symbol 对象, 去到 StringTable,StringTable 支持以 Symbol 为 key 来查询是否已经有内容匹配的项存在与否, 存在则直接返回匹配项,不存在则创建出内容匹配的java.lang.String 对象,然后将其引用放入 StringTable。

0 回复 有任何疑惑可以回复我~
  • 提问者 luyuni #1
    非常感谢老师!
    回复 有任何疑惑可以回复我~ 2019-03-03 19:08:21
  • 对于这种 全局变量是存在哪呢 网上有些人说 在方法区 有些人说全局变量是属于对象的,对象在堆中所以该变量在堆中
    回复 有任何疑惑可以回复我~ 2019-12-05 09:35:10
  • 翔仔 回复 qq_不弃_7 #3
    变量的值存在堆中
    回复 有任何疑惑可以回复我~ 2019-12-05 22:49:50
翔仔 2019-03-03 11:04:11

同学好,这种方式是在构造string的时候放入的字符串常量池

0 回复 有任何疑惑可以回复我~
  • 提问者 luyuni #1
    没有明白
    回复 有任何疑惑可以回复我~ 2019-03-03 11:05:38
  • 具体在第一次引用该项的 ldc 指令被第一次执行到的时候。 解析 CONSTANT_String 时(该代码也就是执行到 Strings = "hello"; 的时候),根据 index 去运行时常量池查找 CONSTANT_UTF8,然后找到对应的 Symbol 对象, 去到 StringTable,StringTable 支持以 Symbol 为 key 来查询是否已经有内容匹配的项存在与否, 存在则直接返回匹配项,不存在则创建出内容匹配的java.lang.String 对象,然后将其引用放入 StringTable。
    
    这么说hello这个字符串在运行时常量池与字符串常量池都有一份是吗?
    回复 有任何疑惑可以回复我~ 2019-12-06 10:06:04
  • 翔仔 回复 qq_不弃_7 #3
    同学好,不一定呢,jdk8以后,字符串常量池里可以保存实际的值或者指向堆里面字符串的指针。所以有可能是同一份数据
    回复 有任何疑惑可以回复我~ 2019-12-06 23:36:20
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信