StringTable
首先看这样一个面试题
// StringTable [ "a", "b" ,"ab" ] hashtable 结构,不能扩容
public class Demo1_22 {
// 常量池中的信息,都会被加载到运行时常量池中, 这时 a b ab 都是常量池中的符号,还没有变为 java 字符串对象
// ldc #2 会把 a 符号变为 "a" 字符串对象
// ldc #3 会把 b 符号变为 "b" 字符串对象
// ldc #4 会把 ab 符号变为 "ab" 字符串对象
public static void main(String[] args) {
String s1 = "a"; // 懒惰的
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2; // new StringBuilder().append("a").append("b").toString() new String("ab")
String s5 = "a" + "b"; // javac 在编译期间的优化,结果已经在编译期确定为ab
System.out.println(s3 == s4); // false
System.out.println(s3 == s5); // true
}
}
我们从字节码的角度来分析结果
首先反编译该类代字节码,输入命令:
javap -v Demo1_22.class // -v显示详细信息
得到结果:
Classfile /D:/work_folder/java_studying/idea_workspace/jvm/out/production/jvm/cn/itcast/jvm/t1/stringtable/Demo1_22.class
Last modified 2019-12-8; size 1039 bytes
MD5 checksum 9efed67948c7dacf9ddb854ca18f8c2b
Compiled from "Demo1_22.java"
public class cn.itcast.jvm.t1.stringtable.Demo1_22
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #12.#36 // java/lang/Object."<init>":()V
#2 = String #37 // a
#3 = String #38 // b
#4 = String #39 // ab
#5 = Class #40 // java/lang/StringBuilder
#6 = Methodref #5.#36 // java/lang/StringBuilder."<init>":()V
#7 = Methodref #5.#41 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#8 = Methodref #5.#42 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#9 = Fieldref #43.#44 // java/lang/System.out:Ljava/io/PrintStream;
#10 = Methodref #45.#46 // java/io/PrintStream.println:(Z)V
#11 = Class #47 // cn/itcast/jvm/t1/stringtable/Demo1_22
#12 = Class #48 // java/lang/Object
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 LocalVariableTable
#18 = Utf8 this
#19 = Utf8 Lcn/itcast/jvm/t1/stringtable/Demo1_22;
#20 = Utf8 main
#21 = Utf8 ([Ljava/lang/String;)V
#22 = Utf8 args
#23 = Utf8 [Ljava/lang/String;
#24 = Utf8 s1
#25 = Utf8 Ljava/lang/String;
#26 = Utf8 s2
#27 = Utf8 s3
#28 = Utf8 s4
#29 = Utf8 s5
#30 = Utf8 StackMapTable
#31 = Class #23 // "[Ljava/lang/String;"
#32 = Class #49 // java/lang/String
#33 = Class #50 // java/io/PrintStream
#34 = Utf8 SourceFile
#35 = Utf8 Demo1_22.java
#36 = NameAndType #13:#14 // "<init>":()V
#37 = Utf8 a
#38 = Utf8 b
#39 = Utf8 ab
#40 = Utf8 java/lang/StringBuilder
#41 = NameAndType #51:#52 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#42 = NameAndType #53:#54 // toString:()Ljava/lang/String;
#43 = Class #55 // java/lang/System
#44 = NameAndType #56:#57 // out:Ljava/io/PrintStream;
#45 = Class #50 // java/io/PrintStream
#46 = NameAndType #58:#59 // println:(Z)V
#47 = Utf8 cn/itcast/jvm/t1/stringtable/Demo1_22
#48 = Utf8 java/lang/Object
#49 = Utf8 java/lang/String
#50 = Utf8 java/io/PrintStream
#51 = Utf8 append
#52 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#53 = Utf8 toString
#54 = Utf8 ()Ljava/lang/String;
#55 = Utf8 java/lang/System
#56 = Utf8 out
#57 = Utf8 Ljava/io/PrintStream;
#58 = Utf8 println
#59 = Utf8 (Z)V
{
public cn.itcast.jvm.t1.stringtable.Demo1_22();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/itcast/jvm/t1/stringtable/Demo1_22;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=6, args_size=1
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: ldc #4 // String ab
8: astore_3
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: astore 4
29: ldc #4 // String ab
31: astore 5
33: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
36: aload_3
37: aload 4
39: if_acmpne 46
42: iconst_1
43: goto 47
46: iconst_0
47: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V
50: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
53: aload_3
54: aload 5
56: if_acmpne 63
59: iconst_1
60: goto 64
63: iconst_0
64: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V
67: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 6
line 14: 9
line 15: 29
line 16: 33
line 17: 50
line 18: 67
LocalVariableTable:
Start Length Slot Name Signature
0 68 0 args [Ljava/lang/String;
3 65 1 s1 Ljava/lang/String;
6 62 2 s2 Ljava/lang/String;
9 59 3 s3 Ljava/lang/String;
29 39 4 s4 Ljava/lang/String;
33 35 5 s5 Ljava/lang/String;
StackMapTable: number_of_entries = 4
frame_type = 255 /* full_frame */
offset_delta = 46
locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String, class java/lang/String, class java/lang/String, c
lass java/lang/String ]
stack = [ class java/io/PrintStream ]
frame_type = 255 /* full_frame */
offset_delta = 0
locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String, class java/lang/String, class java/lang/String, c
lass java/lang/String ]
stack = [ class java/io/PrintStream, int ]
frame_type = 79 /* same_locals_1_stack_item */
stack = [ class java/io/PrintStream ]
frame_type = 255 /* full_frame */
offset_delta = 0
locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String, class java/lang/String, class java/lang/String, c
lass java/lang/String ]
stack = [ class java/io/PrintStream, int ]
}
SourceFile: "Demo1_22.java"
我们从中摘取最重要的一段:
Code:
stack=3, locals=6, args_size=1
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: ldc #4 // String ab
8: astore_3
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: astore 4
29: ldc #4 // String ab
31: astore 5
上面每句的意思可参照jvm指令手册去进行阅读
0: ldc #2 // String a
ldc 把常量池中的项压入栈,即在Constant pool中找到#2,然后将其压入栈。也就是String a
astore_1 // astore_1 将引用类型或returnAddress类型值存入局部变量1
也就是LocalVariableTable中的这一行
3 65 1 s1 Ljava/lang/String;
其他类似,
在索引9的位置:
9: new #5 // class java/lang/StringBuilder
这 就是创建了一个StringBuilder对象,
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
""
StringTable的更多相关文章
- ue4 StringTable
StringTable 用法很简单可以参考 https://blog.csdn.net/u012801153/article/details/80393531 这里只说说上面文章中没提到的小技巧 T ...
- JVM 专题十六:StringTable
1. String的基本特性 String:字符串,使用一对""引起来表示. String声明为final的,不可被继承. String实现了Serializable接口:表示字符 ...
- StringTable结构以及基本调优
StringTable底层实现类似于HashTable,由数组和链表组成,数组又称为桶数组.比如有这样一段代码: public class Demo4 { public static void mai ...
- 【JVM之内存与垃圾回收篇】StringTable
StringTable String的基本特性 String:字符串,使用一对 "" 引起来表示 String s1 = "Nemo"; // 字面量的定义方式 ...
- JVM系列之:String.intern和stringTable
目录 简介 intern简介 intern和字符串字面量常量 分析intern返回的String对象 分析实际的问题 G1中的去重功能 总结 简介 StringTable是什么?它和String.in ...
- 看了这篇文章,我搞懂了StringTable
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 String应该是Java ...
- JVM字符串常量池StringTable
String的基本特性 String:字符串,使用一对""引起来表示. String sl = "hello"://字面量的定义方式: String s2 = ...
- 第 13 章 StringTable详解
目录 第 13 章 StringTable 1.String 的基本特性 1.1.String 概述 1.2.String 的基本特征 1.3.String 的底层结构 2.String 的内存分配 ...
- JVM 中的StringTable
是什么 字符串常量池是 JVM 中的一个重要结构,用于存储JVM运行时产生的字符串.在JDK7之前在方法区中,存储的是字符串常量.而字符串常量池在 JDK7 开始移入堆中,随之而来的是除了存储字符串常 ...
随机推荐
- C++中的Point类与vector类的简单处理
首先设计Vector与Point的表示方法,再依次完善两个类中的构造函数,复制构造函数等. 向量由两个点表示,当进行运算的时候,转化起点坐标为(0,0): 第14行:由于Vector需要用到Point ...
- English--介词省略句型与总结
English|介词省略句型与总结 本篇文章将会介绍介词的省略与整个语法内容的总结.小板凳都带上,准备开始了! 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识点的描述.力求不含任 ...
- CentOS 7.0 使用yum 安装 Mariadb
第一步: 使用命令查看是否已经安装: mysql -u root -p 返回 Enter password: 时表示已经安装成功的,需要卸载安装. 第二步: 使用yum直接安装mariadb,注意带 ...
- maven 镜像仓库 setting.xml修改 & 手动导入的包如何加到maven里面
如果不知道maven安装路径IDEA中打File->Settings 再点Build->Maven右边看maven安装路径,打开这个路径,再打开conf/settings.xml文件 ...
- 完整的房间类游戏解决方案AiJ
介绍 AiJ是一套完整的房间类游戏解决方案,支持无限水平扩展来满足更大的人数承载,并且提供了良好的调试接口. 主要模块包括: 注册中心 大厅服务 游戏服务 亲友圈服务 运营管理系统 CocosCrea ...
- Java集合目录
java集合学习(1):集合框架 java集合学习(2):Map和HashMap Java集合学习(4):HashTable Java集合学习(5):LinkedHashMap Java集合学习(6) ...
- Django学习之十四:Django ORM继承关系
目录 Django ORM继承关系 1. SINGLE_TABLE(django好像不支持) 2. TABLE_PER_CLASS 3. JOINED 4. 代理继承 Django ORM继承关系 参 ...
- Django框架(九)-- 多表操作:一对一、一对多、多对多的增删改,基于对象/双下划线的跨表查询、聚合查询、分组查询、F查询与Q查询
一.创建多表模型 一对一:OneToOneField 一对多:ForeignKey 多对多:ManyToManyField 创建表时,会自动添加一个nid字段,并且自增,所以id可以不用手动创建 On ...
- angular6 页面加载数据时的loading提示
使用npm安装ngx-loading模块 npm install --save ngx-loading 在app.module.ts中导入模块 import { BrowserModule } fro ...
- MongoDB在windows及linux环境下安装
linux下安装配置 整理中... windows下安装配置 1.下载: https://www.mongodb.com/download-center?jmp=nav 2.解压到D盘 3.D:\下创 ...