通过Java字节码发现有趣的内幕之String篇(上)(转)
原文出处: jaffa
很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西。这里没有对Java字节码知识进行介绍,如果想了解更多的Java字节码或对其感兴趣的朋友可以先阅读字节码基础:JVM字节码初探。
String字面量可以通过’==’判断两个字符串是否相同,是因为大家都知道’==’是用来判断两个对象的值引用地址是否一致,两个值一样的字符串字面量定义是否指向同一个值内存地址呢?答案是肯定的。
|
1
2
3
4
5
6
7
8
9
10
|
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文件的字节码。
|
1
|
javap -v com.jaffa.test.string.ConstPoolTest |

在Constant pool列表中看到#16为一个String类型并值指向#17,而#17是一个utf8字符集编码值为strVal_1,所以#16和#17最终表达就是在常量池中有个String类型值为strVal_1的常量数据。
那接下来需要确认str1和str2两个变量值是否都是指向#16呢?

|
1
2
3
4
5
|
//ldc表示将一个常量加载到操作数栈 0: ldc #16 //将#16对应的常量值加载到操作数栈中 2: astore_1 //将当前操作数栈中赋于变量1,即str1 3: ldc #16 //再次将#16对应的常量值加载到操作数栈中 5: astore_2 //将当前操作数栈中赋于变量2,即str2 |
从上面字节码执行来看,str1和str2都是被赋于同一个常量值,由此可以得出两个变更指向同一个内存地址。
通过同样的方式,我们来看一下如果是非字面量的情况会是怎么样的,Java代码如下:
|
1
2
3
4
5
6
7
8
9
10
|
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变量的字节码指令发生了变化,如下现两截图:


|
1
2
3
4
5
6
7
8
|
//ldc表示将一个常量加载到操作数栈 0: ldc #16 //将#16对应的常量值加载到操作数栈中 2: astore_1 //将当前操作数栈中赋于变量1,即str1 3: new #18 //创建了一个类实例,#18指向一个实例类型String 6: dup //配置上行完成操作栈指令 7: ldc #16 //将#16对应的常量值加载到操作数栈中 9: invokespecial #20 //调用String实例初始化方法,并将#16输入12: astore_2 //将new出来的实例赋于变量2,即str2 |
这时str2变量是创建一个新的内存地址,而非直接指向#16常量内存地址,所以str1==str2的结果为false。同时可以看到通过new String()带来看更多的字节码指令操作,运行上花费了更多的系统资源。
本系列:
http://www.importnew.com/18785.html
通过Java字节码发现有趣的内幕之String篇(上)(转)的更多相关文章
- JVM 内部原理(六)— Java 字节码基础之一
JVM 内部原理(六)- Java 字节码基础之一 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...
- 从Java源码到Java字节码
Java最主流的源码编译器,javac,基本上不对代码做优化,只会做少量由Java语言规范要求或推荐的优化:也不做任何混淆,包括名字混淆或控制流混淆这些都不做.这使得javac生成的代码能很好的维持与 ...
- 硬核万字长文,深入理解 Java 字节码指令(建议收藏)
Java 字节码指令是 JVM 体系中非常难啃的一块硬骨头,我估计有些读者会有这样的疑惑,"Java 字节码难学吗?我能不能学会啊?" 讲良心话,不是我谦虚,一开始学 Java 字 ...
- 掌握Java字节码(转)
Java是一门设计为运行于虚拟机之上的编程语言,因此它需要一次编译,处处运行(当然也是一次编写,处处测试).因此,安装到你系统上的JVM是原生的程序,而运行在它之上的代码是平台无关的.Java字节码就 ...
- Java字节码操纵框架ASM小试
本文主要内容: ASM是什么 JVM指令 Java字节码文件 ASM编程模型 ASM示例 参考资料汇总 JVM详细指令 ASM是什么 ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既 ...
- Java:从面试题“i++和++i哪个效率高?"开始学习java字节码
今天看到一道面试题,i++和++i的效率谁高谁低. 面试题的答案是++i要高一点. 我在网上搜了一圈儿,发现很多回答也都是同一个结论. 如果早个几年,我也会认同这个看法,但现在我负责任的说,这个结论是 ...
- Java字节码基础[转]
原文链接:http://it.deepinmind.com/jvm/2014/05/24/mastering-java-bytecode.html Java是一门设计为运行于虚拟机之上的编程语言,因此 ...
- 从 HelloWorld 看 Java 字节码文件结构
很多时候,我们都是从代码层面去学习如何编程,却很少去看看一个个 Java 代码背后到底是什么.今天就让我们从一个最简单的 Hello World 开始看一看 Java 的类文件结构. 在开始之前,我们 ...
- 空手套白狼,硬阅java字节码class文件
如下,是一些java字节码也就是原始的class文件,当应用部署到线上之后,我们能够看到的也就是这样的字样了.那么怎样解呢?就让我们一起,来解读解读字节码吧! Offset A B C D E F C ...
随机推荐
- iTextSharp使用字体设置摘录
用iTextSharp做pdf转换的时候,需要添加水印.文字水印的时候,需要设置字体,查了下文档.摘录下解决方案. iText中输出中文,有三种方式: 1.使用iTextAsian.jar中的字体 ...
- Effective C++ 第二版 8) 写operator new 和operator delete 9) 避免隐藏标准形式的new
条款8 写operator new 和operator delete 时要遵循常规 重写operator new时, 函数提供的行为要和系统缺省的operator new一致: 1)正确的返回值; 2 ...
- linux pthread之学习篇
在应用程序编程中,为了不影响与用户交互的性能,通常需要创建新的线程来处理一些比较耗时的. 不影响用户体验的工作.而这又通常分为两种情况: (1)需要临时创建一个线程来做某件特定的事,等事情做完时线程即 ...
- js传真实地址 C:\fakepath
js给action传真是地址的时候,处于安全,传到action中 浏览器会改变路径变为C:\fakepath\ftp.txt,但是原始路径却是 C:\Documents and Settings\Ad ...
- [置顶] Ftp客户端概要设计
Ftp客户端概要设计 1.概述 ftp是基于TCP的文件传输协议,主要是用于控制远程文件,如下载.上传.续传.重命名.删除等.其命令是基于可见字符,易于理解的方式交互的.客户端与服务器端的交互遵循一应 ...
- 一int考虑什么类型的多少字节
一int表示的字节数? 问题是,我们经常得到的答案4. 但int究竟占多少个字节,却跟你的机器环境有关. As you can see, the typical data type sizes mat ...
- javascript(五)验证
<input id="domo" type="text"> <script> function my_function(){ var ...
- jquery怎么在点击li标签之后添加一个在class,点击下一个li时删除上一个class?
思路:点击当前li元素后是用removeClass()删除所有兄弟元素(使用siblings()获取)的class样式,然后使用addClass()为当前li添加class. 具体演示如下: 1.HT ...
- 为Delphi程序增加UAC功能(每个步骤都很详细)
相关资料:http://bbs.csdn.net/topics/320071356# 操作方法: 在Source\VCL目录下应该有这样两个文件sample.manifest和WindowsXP.rc ...
- 使用ffmpeg 对视频截图,和视频转换格式
//执行CMD命令方法 public static void CmdProcess(string command)//调用CMD { //实例化一个进程类 ...