锁定老帖子 主题:【总结】String in Java
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-24
先赞一个,Q:
1. 我咋看不到字节流图。 2.还请博主揭开“四个不同类型的常量表”的面纱。 |
|
返回顶楼 | |
发表时间:2009-11-24
"最后将堆中StringBuilder对象的地址赋给变量sab",sab是一个string,能指导到一个stringbuilder?
|
|
返回顶楼 | |
发表时间:2009-11-25
最后修改:2009-11-25
mwei 写道 先赞一个,Q:
1. 我咋看不到字节流图。 2.还请博主揭开“四个不同类型的常量表”的面纱。 1、class文件是二进制字节流。其结构是按顺序组成的有意义的项。比如说class文件字节流中最开始的4个字节是magic项,后面4个字节是主、次Version项,然后是Constant pool常量池项.... 。字节流逻辑图就是(http://dl.iteye.com/upload/picture/pic/50015/1f7bd098-2b41-3f95-b129-460190f351ba.gif)左侧部分。 2、所谓“四个不同类型的常量表”,是指在这篇文章中我用HelloWord代码做例子,这段代码的.class文件在常量池中有四种不同类型的常量表组成。其实常量表的种类远不只这些。在《深入Java虚拟机》第二版第6章P124有详细说明。这里帖点出来: 【表 常量池标志】 入口类型 标志值 描述 CONSTANT_Utf8 1 UTF-8编码的字符串 CONSTANT_Integer 3 int类型字面值 CONSTANT_Float 4 float类型字面值 CONSTANT_Long 5 long类型字面值 CONSTANT_Double 6 double类型字面值 CONSTANT_Class 7 对一个类或接口的符号引用 CONSTANT_String 8 String类型字面值 CONSTANT_Fieldref 9 对一个字段的符号引用 CONSTANT_Methodref 10 对一个类中声明的方法的符号引用 CONSTANT_InterfaceMethodref 11 对一个接口中声明的方法的符号引用 CONSTANT_NameAndType 12 对一个字段或方法的部分符号引用 |
|
返回顶楼 | |
发表时间:2009-11-25
Heart.X.Raid 写道 1、class文件是二进制字节流。其结构是按顺序组成的有意义的项。比如说class文件字节流中最开始的4个字节是magic项,后面4个字节是主、次Version项,然后是Constant pool常量池项.... 。字节流逻辑图就是(http://dl.iteye.com/upload/picture/pic/50015/1f7bd098-2b41-3f95-b129-460190f351ba.gif)左侧部分。 2、所谓“四个不同类型的常量表”,是指在这篇文章中我用HelloWord代码做例子,这段代码的.class文件在常量池中有四种不同类型的常量表组成。其实常量表的种类远不只这些。在《深入Java虚拟机》第二版第6章P124有详细说明。这里帖点出来: 【表 常量池标志】 入口类型 标志值 描述 CONSTANT_Utf8 1 UTF-8编码的字符串 CONSTANT_Integer 3 int类型字面值 CONSTANT_Float 4 float类型字面值 CONSTANT_Long 5 long类型字面值 CONSTANT_Double 6 double类型字面值 CONSTANT_Class 7 对一个类或接口的符号引用 CONSTANT_String 8 String类型字面值 CONSTANT_Fieldref 9 对一个字段的符号引用 CONSTANT_Methodref 10 对一个类中声明的方法的符号引用 CONSTANT_InterfaceMethodref 11 对一个接口中声明的方法的符号引用 CONSTANT_NameAndType 12 对一个字段或方法的部分符号引用 昨天网络不行,没看到图。现已看到图,清楚多了,谢谢博主。 钻研精神&&分享心理一般是大师所有。 |
|
返回顶楼 | |
发表时间:2009-11-25
最后修改:2009-11-25
midstr 写道 "最后将堆中StringBuilder对象的地址赋给变量sab",sab是一个string,能指导到一个stringbuilder?
请看下例子 public class StringTest { public static void main(String[] args) { String s1 = "a"; String s2 = "a2"; String s3 = s1+s2; String s4 = "aa2"; System.out.println(s3==s4); } } StringTest的class文件 public static void main(java.lang.String[] args); 0 ldc <String "a"> [16] 2 astore_1 [s1] 3 ldc <String "a2"> [18] 5 astore_2 [s2] 6 new java.lang.StringBuilder [20] 9 dup 10 aload_1 [s1] 11 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [22] 14 invokespecial java.lang.StringBuilder(java.lang.String) [28] 17 aload_2 [s2] 18 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder[31] 21 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [35] 24 astore_3 [s3] 25 ldc <String "aa2"> [39] 27 astore 4 [s4] 29 getstatic java.lang.System.out : java.io.PrintStream [41] 32 aload_3 [s3] 33 aload 4 [s4] 35 if_acmpne 42 38 iconst_1 39 goto 43 42 iconst_0 43 invokevirtual java.io.PrintStream.println(boolean) : void [47] 46 return 18 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder[31] 请注意红色标注,谢谢LZ分享! |
|
返回顶楼 | |
发表时间:2009-11-26
受益匪浅啊!
|
|
返回顶楼 | |
发表时间:2009-11-27
楼主,关于ldc指令的解释,最好强调一下,ldc “Push item from runtime constant pool”,即该指令将常量池中的“东西”push到栈。因为java的指令是基于栈的而不是基于寄存器的嘛。下面的方面需要用到这个push到栈的“东西”。
|
|
返回顶楼 | |
发表时间:2009-11-28
Heart.X.Raid 写道
作者:Java标准类库有几千个类,唯独String不太一样。为什么这么说?就因为每次上网冲杯Java时,都能看到关于String无休无止的争论。还是觉得有必要让这个讨厌又很可爱的String美眉,赤裸裸的站在我们这些Java色狼面前了。嘿嘿....
【镜头1】 String对象的创建
其中,在class文件中有一个非常重要的项——常量池 。这个常量池专门放置源代码中的常量信息(并且不同的常量存放在不同标志的常量表中)。如上图右侧是HelloWorld代码中的常量表(HelloWorld代码如下),其中有四个不同类型的常量表(四个不同的常量池入口)。关于常量池的具体细节,请参照《深入Java虚拟机》第二版第6章。 public class HelloWorld{ void hello(){ System.out.println("Hello world"); } } 显然,HelloWorld代码中的"Hello world"被编译之后,可以清楚的看到存放在了class二进制流的常量池项中(上图右侧红框区域)。并且我们还发现常量池中专门有为String类型设置的常量表 。也就是说,在编译阶段,就已经将代码中的这种("****")形式作为了字符串常量存放在常量池中了 ,这一点和下面代码中出现的整形常量(142),浮点型常量(12.1)等的处理是没有区别的。 String s="Hello world"; (2) Java虚拟机运行class文件
(3) 操作码助忆符指令集 0 new java.lang.String [15] 3 dup 4 ldc <String "Hello word"> [17] 6 invokespecial java.lang.String(java.lang.String) [19] 9 astore_1 [s] 10 retur 下面通俗的解释一下这些指令,详细见《深入Java虚拟机》第二版附表:按操作码助忆符排列的指令集。
将String s="Hello world";编译成class文件后的指令: 0 ldc <String "Hello world"> [15] 2 astore_1 [str] 3 return ★ ldc指令:在内存的方法区常量池中找到String类型字面值常量表 的入口,然后定位到的"Hello word"所在内存中的位置(如果常量池中没有"Hello word",则会在其中添加一个"Hello word")。
镜头总结: String类型脱光了其实也很普通。真正让她神秘的原因就在于String类型字面值常量表 的存在。
相关问题解决 (问题1) 代码1 代码2 String sa=new String("Hello world"); String sc="Hello world"; (问题2) 代码1 代码2
|
|
返回顶楼 | |
发表时间:2009-11-29
insideJVM 是一本好书 。
指正楼主: ldc指令 的作用是把常量压入栈 invokespecial指令 是弹出栈顶对象,然后执行出栈对象的指定方法 |
|
返回顶楼 | |
发表时间:2009-11-30
呵呵 楼主扒得好光啊!
学习啦 |
|
返回顶楼 | |