文档章节

通过Java字节码发现有趣的内幕之String篇(一)

jaffa
 jaffa
发布于 2015/08/28 17:39
字数 967
阅读 2972
收藏 17

很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西。这里没有对Java字节码知识进行介绍,如果想了解更多的Java字节码或对其感兴趣的朋友可以先阅读字节码基础:JVM字节码初探

String字面量可以通过'=='判断两个字符串是否相同,是因为大家都知道'=='是用来判断两个对象的值引用地址是否一致,两个值一样的字符串字面量定义是否指向同一个值内存地址呢?答案是肯定的。

package com.jaffa.test.string;

public class ConstPoolTest {
	public static void main(String[] args){
		String str1 = "strVal_1";
		String str2 = "strVal_1";
		//print str1==str2 is true
		System.out.printf("str1==str2 is %b",str1==str2);
	}
}

代码中声明了str1和str2的字面量值都为strVal_1,并且打印出str1==str2为true,说明两个str1和str2变量同时指向同一个字符串常量值的内存地址,下面通过Java字节码来验证这个结果。

在命令行我们通过javap工具来查看一个class文件的字节码。

javap -v com.jaffa.test.string.ConstPoolTest

   

在Constant pool列表中看到#16为一个String类型并值指向#17,而#17是一个utf8字符集编码值为strVal_1,所以#16和#17最终表达就是在常量池中有个String类型值为strVal_1的常量数据。

那接下来需要确认str1和str2两个变量值是否都是指向#16呢?

   

 //ldc表示将一个常量加载到操作数栈
 0: ldc           #16     //将#16对应的常量值加载到操作数栈中            
 2: astore_1              //将当前操作数栈中赋于变量1,即str1
 3: ldc           #16     //再次将#16对应的常量值加载到操作数栈中
 5: astore_2              //将当前操作数栈中赋于变量2,即str2

从上面字节码执行来看,str1和str2都是被赋于同一个常量值,由此可以得出两个变更指向同一个内存地址。

通过同样的方式,我们来看一下如果是非字面量的情况会是怎么样的,Java代码如下:

package com.jaffa.test.string;

public class ConstPoolTest {
	public static void main(String[] args){
		String str1 = "strVal_1";
		String str2 = new String("strVal_1");
		
		System.out.printf("str1==str2 is %b",str1==str2);
	}
}

上面代码输出结果为false,通过javap查看发现str2变量的字节码指令发生了变化,如下现两截图:

     

   

 //ldc表示将一个常量加载到操作数栈
 0: ldc           #16     //将#16对应的常量值加载到操作数栈中            
 2: astore_1              //将当前操作数栈中赋于变量1,即str1
 3: new           #18     //创建了一个类实例,#18指向一个实例类型String
 6: dup                   //配合上行完成栈值复制操作指令,将new重新压入栈顶
 7: ldc           #16     //将#16对应的常量值加载到操作数栈中 
 9: invokespecial #20     //调用String实例初始化方法,并将#16输入
12: astore_2              //将new出来的实例赋于变量2,即str2

这时str2变量是创建一个新的内存地址,而非直接指向#16常量内存地址,所以str1==str2的结果为false。同时可以看到通过new String()带来看更多的字节码指令操作,运行上花费了更多的系统资源。

下篇:将通过字节码发现String操作内幕

© 著作权归作者所有

jaffa
粉丝 27
博文 10
码字总数 9735
作品 0
福州
程序员
私信 提问
加载中

评论(7)

jaffa
jaffa 博主

引用来自“os_china_code”的评论

6: dup //配置上行完成操作栈指令

上面这行解析没看懂,能不能用更大白话给解析下呗
不好意思,这里有个词订错了,是配合不是配置; 再来解析下dup这个指令是用于栈复制的,在这个地方的作用就是将new的结果复制到栈顶中,主要是为了下面使用invokespecial指令时能知道是调用谁的方法。6,7,9三个指令完成了new String("strVal_1")的代码。
o
os_china_code
6: dup //配置上行完成操作栈指令

上面这行解析没看懂,能不能用更大白话给解析下呗
jaffa
jaffa 博主

引用来自“YanbinQ”的评论

很佩服楼主的学习精神, String 是放在常量池中, new String("abc").intern() == new String("abc").intern() 是 true
YanbinQ
YanbinQ
很佩服楼主的学习精神, String 是放在常量池中, new String("abc").intern() == new String("abc").intern() 是 true
f
fzwf
797979797979[79][79][79]
[79][79][79][79][79][79][79][79][79]
[79][79][79][79][79][79][79][79][79]
[79][79]
哎啊-哈哈
哎啊-哈哈
学习
天凉好个秋
天凉好个秋
学习了,谢谢
【JVM系列】一步步解析java执行内幕

对于任何一门语言,要想达到精通的水平,研究它的执行原理(或者叫底层机制)不失为一种良好的方式。在本篇文章中,将重点研究java源代码的执行原理,即从程 序员编写JAVA源代码,到最终形成产...

java菜分享
03/02
0
0
深入理解JVM内幕:从基本结构到Java 7新特

摘要:许多没有深入理解JVM的开发者也开发出了很多非常好的应用和类库。不过,如果你更加理解JVM的话,你就会更加理解Java,这样你会有助于你处理类似于我们前面的案例中的问题。 每个Java开...

开源中国驻成都办事处
2012/12/06
0
1
大概优秀的java程序员都要会分析class文件吧

相信大家在学java的时候都会听到这样的一些结论: enum 是一个类 泛型的实现使用了类型擦除技术 非静态内部类持有外部类的引用 需要将自由变量声明成final才能给匿名内部类访问 ... 初学的时候...

嘉伟咯
03/22
0
0
JDK8中Lambda表达式底层实现浅析(一)

1.前言 2014年十月份的时候Debug了下Lambda的实现代码, 大概了解了Lambda的实现, 昨天回忆了下, 发现以忘光, 还是写篇博客吧, 方便记忆 这篇文章是我本地Debug后记录下来的所见所闻, 不一定完...

德胜
2015/01/13
0
1
Java 字节码结构剖析一 : 常量池

来源:拿笔小星_ , blog.csdn.net/u013096088/article/details/83047282 这篇博客开始,我打算带大家去解读一下JVM平台下的字节码文件(熟悉而又陌生的感觉)。众所周知,Class文件包含了我...

木子SMZ
2018/11/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

中奖名单 | “赠书活动”中奖名单公布

在上周的赠书活动中, 小伙伴们踊跃参与! 京小云也很认真地进行了统计, 非常感谢大家的参与和支持! 下面公布中奖的名单~ 请中奖的小伙伴于5个工作日内 在微信公众号后台留下你的联系地址 ...

京东云技术新知
21分钟前
1
0
云原生生态周报 Vol. 11 | K8s 1.16 早知道

业界要闻 Pivotal 发布了完全基于 Kubernetes 的 Pivotal Application Service(PAS)预览版 这意味着 Pivotal 公司一直以来在持续运作的老牌 PaaS 项目 Cloud Foundry (CF)终于得以正式拥...

阿里巴巴云原生
22分钟前
0
0
低版本xcode真机调试iOS 12.3.1

老款mac pro已经升级不了系统了,导致最新版的xcode10.2及以上也安装不了,最新版的ios12.3.1也联机调试不了,apple是要逼着大家升级硬件啊,软件即服务,就是这样来的,大部分计算机软件公司...

swingcoder
22分钟前
4
0
浅谈堆排序

一:定义 堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆排序是一种树形选择排序,在排序过程中可以把元素看成是一颗完全二叉树,每个节点都大(小)于它的两个子...

无名氏的程序员
24分钟前
2
0
Alibaba Cloud Linux 2 开源后又有什么新动作?

阿里妹导读:2019 年 4 月,Alibaba Cloud Linux 2 (Aliyun Linux 2) 正式开源。时至今日,已经走过三个月的里程。在这段时间内,这个刚诞生不久的为阿里云 ECS 环境定制优化的 Linux 操作系...

阿里云官方博客
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部