A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 牧风   /  2016-7-30 22:05  /  2150 人查看  /  29 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

s实在字符串常量池中创建  s2堆内存中创建对象
回复 使用道具 举报
cat73 黑马帝 2016-7-31 01:02:19
22#
本帖最后由 cat73 于 2016-7-31 09:25 编辑
qetu001212 发表于 2016-7-31 00:04
为何冯佳老师和你说的不一样?

如果你认为我说错了,请拿证据打我脸,但请不要说这是谁说过的。谢谢。
为了回答这个问题,我花了些时间去看 OpenJDK 的源代码:
http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/interpreter/bytecodeInterpreter.cpp#l2111
在上面这个地方可以看到 ldc 的实现
2134 行是 ldc String 的情况:
[C++] 纯文本查看 复制代码
          case JVM_CONSTANT_String:
            {
              oop result = constants->resolved_references()->obj_at(index);
              if (result == NULL) {
                CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
                SET_STACK_OBJECT(THREAD->vm_result(), 0);
                THREAD->set_vm_result(NULL);
              } else {
                VERIFY_OOP(result);
                SET_STACK_OBJECT(result, 0);
              }
            break;
            }

可以看到,ldc 只是简单的从常量池里尝试获取对象,如果返回 null (没找到),则抛出异常,并不会在 ldc 这里 new String。

而 "abc" 就是通过 ldc 来获取的,也就是说,"abc" 不是 ldc 创建的,所以,这句代码执行的时候并不会创建"abc",所以,这句代码只创建了一个对象。

有兴趣的话也可以看看 ldc 的规范:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ldc

评分

参与人数 1黑马币 +3 收起 理由
qetu001212 + 3 赞一个!

查看全部评分

回复 使用道具 举报 1 0
ylca 中级黑马 2016-7-31 09:04:21
23#
一个是拿一个是创建
回复 使用道具 举报
一个在方法区的常量池中,一个NEW在堆内存中
回复 使用道具 举报
第一个在常量池,第二个在堆内存,地址值不同
回复 使用道具 举报
cat73 发表于 2016-7-31 01:02
如果你认为我说错了,请拿证据打我脸,但请不要说这是谁说过的。谢谢。
为了回答这个问题,我花了些时间去 ...

初学者,在学基础,看不懂源码,已送上3黑马币请求原谅~~~
回复 使用道具 举报
shockzwel1 发表于 2016-7-30 23:31
同学  来一把狼人杀吧

你也玩网杀?
回复 使用道具 举报
cat73 黑马帝 2016-8-1 23:52:52
28#

回复 使用道具 举报
cat73 黑马帝 2016-8-2 01:12:03
29#
本帖最后由 cat73 于 2016-8-2 01:15 编辑
qetu001212 发表于 2016-7-31 00:04
为何冯佳老师和你说的不一样?

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.5
  1. The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.
复制代码

一个更精准的描述,常量是在类加载时创建的。
所以下面的代码只创建了一个对象
new String("abc");

这条规范在 Java 6 就已经有了:https://docs.oracle.com/javase/specs/jvms/se6/html/Overview.doc.html#22972

回复 使用道具 举报
第一个常量池,第二个有两个对象,一个是在堆内存中创建String类对象,一个是在常量池中创建“abcd”对象
回复 使用道具 举报
12
您需要登录后才可以回帖 登录 | 加入黑马