原文出处: 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篇(上)(转)的更多相关文章

  1. JVM 内部原理(六)— Java 字节码基础之一

    JVM 内部原理(六)- Java 字节码基础之一 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

  2. 从Java源码到Java字节码

    Java最主流的源码编译器,javac,基本上不对代码做优化,只会做少量由Java语言规范要求或推荐的优化:也不做任何混淆,包括名字混淆或控制流混淆这些都不做.这使得javac生成的代码能很好的维持与 ...

  3. 硬核万字长文,深入理解 Java 字节码指令(建议收藏)

    Java 字节码指令是 JVM 体系中非常难啃的一块硬骨头,我估计有些读者会有这样的疑惑,"Java 字节码难学吗?我能不能学会啊?" 讲良心话,不是我谦虚,一开始学 Java 字 ...

  4. 掌握Java字节码(转)

    Java是一门设计为运行于虚拟机之上的编程语言,因此它需要一次编译,处处运行(当然也是一次编写,处处测试).因此,安装到你系统上的JVM是原生的程序,而运行在它之上的代码是平台无关的.Java字节码就 ...

  5. Java字节码操纵框架ASM小试

    本文主要内容: ASM是什么 JVM指令 Java字节码文件 ASM编程模型 ASM示例 参考资料汇总 JVM详细指令 ASM是什么 ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既 ...

  6. Java:从面试题“i++和++i哪个效率高?"开始学习java字节码

    今天看到一道面试题,i++和++i的效率谁高谁低. 面试题的答案是++i要高一点. 我在网上搜了一圈儿,发现很多回答也都是同一个结论. 如果早个几年,我也会认同这个看法,但现在我负责任的说,这个结论是 ...

  7. Java字节码基础[转]

    原文链接:http://it.deepinmind.com/jvm/2014/05/24/mastering-java-bytecode.html Java是一门设计为运行于虚拟机之上的编程语言,因此 ...

  8. 从 HelloWorld 看 Java 字节码文件结构

    很多时候,我们都是从代码层面去学习如何编程,却很少去看看一个个 Java 代码背后到底是什么.今天就让我们从一个最简单的 Hello World 开始看一看 Java 的类文件结构. 在开始之前,我们 ...

  9. 空手套白狼,硬阅java字节码class文件

    如下,是一些java字节码也就是原始的class文件,当应用部署到线上之后,我们能够看到的也就是这样的字样了.那么怎样解呢?就让我们一起,来解读解读字节码吧! Offset A B C D E F C ...

随机推荐

  1. Swift - 程序进入后台,以及应用终止时调用的方法

    在AppDelegate中有如下两个方法要注意: applicationDidEnterBackground()  当应用进入后台时起作用 applicationWillTerminate()  当应 ...

  2. bonjour

    首先bonjour并非必须的,可是它的确非常方便,假设没有它我们须要指定ip地址进行局域网的传输,有了它就能够依据服务的详细的名称来选择服务,能够这样来理解bonjour就相当于hostname,我们 ...

  3. 【ASP.NET Web API教程】2.1 创建支持CRUD操作的Web API

    原文 [ASP.NET Web API教程]2.1 创建支持CRUD操作的Web API 2.1 Creating a Web API that Supports CRUD Operations2.1 ...

  4. [置顶] JSP分页,使用Hibernate+mysql

    此代码为博主参考巴巴运动网源码所得,大部分一样,略有修改,在这里分享给大家,也方便自己以后写代码直接copy,看网上很多分页代码JSP里是用JAVA代码,博主原来也是这样,看到源码了解了JSTL,建议 ...

  5. Android broadcast

    发送广播而且接受.发送两个广播 Intent intent = new Intent(); intent.setAction("com.wxq.CUSTOM_INTENT"); s ...

  6. App 运营 推广相关

    基本要素 1.定位和产品 2.取个好名字,一目了然+下载冲动 3.设计一个好图标,有感性和直观的认识 4.做好产品的说明.关键字,截图(前1-2行是重点) 5.做市场的排名(相关因素如下)   (1) ...

  7. RTSP 消息拼装实例代码

    整理了下之前文章提到的RTSP实例的代码,主要是拼装各类消息字段. 首先,抽取一个公共函数,用来根据消息类型,生成不同的format,供sprintf试用. char * GetRTSPCmd( co ...

  8. Windows DIB文件操作具体解释-5.DIB和调色板

    Windows调色板是256色显卡时期的产物,如今显卡最少也是16bit的了.所以调色板基本上是用不到了的. 可是以下几种情况还是须要去使用和了解调色板: 1.在新显卡上保证256色兼容模式的正常执行 ...

  9. RSA加密前言

    RSA:非对称加密,近期因为工作需要需要实现了一个RSA加密方案.查阅文档无数,主要是通过看他们代码及其引用他人的代码基本实现了跨平台的RSA方案.现在唯一的缺陷是加解密花费的时间太多,下周会把加解密 ...

  10. 14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件

    14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件 从历史上看, 所有的InnoDB 表和索引是存储在system 表空间, 这个整体的方法是针对机器专注 ...