引言:

之前一篇文章梳理了String的不变性原则,还提到了一段源码中注释"avoid getfield opcode",当时通过查阅资料发现,这是为了防止 getfield(获取指定类的实例域,并将其值压入到栈顶)这个操作码的执行,这篇文章想从字节码的角度去分析一下。


先看一段代码吧

/**
* Created by chenqimiao on 16/11/29.
*/
public class Main { public char[] chars = new char[10]; public void test() {
System.out.println(chars[0]);
System.out.println(chars[1]);
System.out.println(chars[2]);
} public static void main(String args[]) {
Main m = new Main();
m.test();
}
}

  执行 javap -c Main ,分析一下字节码,查看一下分析后生成的操作码:

查阅"深入理解JVM虚拟机"一书中的虚拟机字节码指令表,试着分析一下test方法下面的code.

4.获取指定的实例域,并将其值压入栈顶

7.将int型0推送至栈顶

8.将char数组指定索引的值推至栈顶

9.调用实例方法

总结一下的话,就是每次获取实例域 推到栈顶,然后推被操作的索引到栈顶,然后取到对应数组的指定索引的值推到栈顶,然后就是调用输出方法了。可以看到输出三次,getfield操作码就调用了三次,假想我们在遍历这个char数组,那象上述写法,要频繁调用getfield操作码了。

我们学一下String源码中的写法,可能能改善一下这个问题。

/**
* Created by chenqimiao on 16/11/29.
*/
public class Main { public char[] chars = new char[10]; public void test() {
char[] chars = this.chars;
System.out.println(chars[0]);
System.out.println(chars[1]);
System.out.println(chars[2]);
} public static void main(String args[]) {
Main m = new Main();
m.test();
}
}

  

  执行 javap -c Main ,分析一下字节码,查看一下分析后生成的操作码:

好了,我把实例变量的数组的引用赋给了一个局部引用了。

我们还是分析一下test方法中的code把

0.将第一个引用类型本地变量推送至栈顶(就是将局部变量引用chars放到栈顶)

1.获取实例域的引用推到栈顶(实例变量的成员chars放到栈顶)

4.将栈顶顶引用类型数值存入指定本地变量(就是把成员变量chars的引用给到局部变量的引用chars,这里是引用值拷贝,不是引用指向内存的值的拷贝)

5.获取指定的实例域,并将其值压入栈顶

8.将第二个引用类型本地变量推送至栈顶

9.将int型0推到栈顶

10.将char数组指定的索引的值压入到栈顶

11.调用实例方法(输出)

在14-20的过程中没有再发生"getfield"操作,而是用aload_1操作码将第二个本地引用(被赋值后的本地引用chars)推至栈顶,就可以执行接下来的一系列操作。

到这里的话"avoid getfield opcode"的意思已经非常清楚明了,在遍历实例的char数组的时候,将实例数组的引用赋值给一个本地引用,不需要频繁调用操作用码"getfield",只需要在第一次对本地引用赋值的时候,调用一次getfield,接下来的遍历取值的时候,只需要将本地引用压入到栈顶。

 

 

String源码中的"avoid getfield opcode"的更多相关文章

  1. String源码中hashCode算法

    针对java中String源码hashcode算法源码分析 /** The value is used for character storage. */ private final char val ...

  2. java面试之String源码中equals具体实现

    废话不多说,直接看代码,注释已经写在上面了: public boolean equals(Object anObject) { if (this == anObject) {//比较两个对象的地址 r ...

  3. 程序兵法:Java String 源码的排序算法(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 <程序兵法:Java Str ...

  4. JDK代码中的优化 之 “avoid getfield opcode”

    在查看String类源码时,常看到注释 /* avoid getfield opcode */ 如 trim()方法 public String trim() { int len = value.le ...

  5. (转)Java中的String为什么是不可变的? -- String源码分析

    背景:被问到很基础的知识点  string  自己答的很模糊 Java中的String为什么是不可变的? -- String源码分析 ps:最好去阅读原文 Java中的String为什么是不可变的 什 ...

  6. java基础进阶一:String源码和String常量池

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8046564.html 邮箱:moyi@moyib ...

  7. 基于JDK1.8的String源码学习笔记

    String,可能是学习Java一上来就学习的,经常用,但是却往往只是一知半解,甚至API有时也得现查.所以还是老规矩,倒腾源码. 一.java doc 这次首先关注String的doc,因为其实作为 ...

  8. Java基础(八)--String(源码)、StringBuffer、StringBuilder

    String源码:基于jdk1.8 public final class String implements Serializable, Comparable<String>, CharS ...

  9. 死啃了String源码之后

    Java源码之String 说在前面: 为什么看源码: 最好的学习的方式就是模仿,接下来才是创造.而源码就是我们最好的模仿对象,因为写源码的人都不是一般的人,所以用心学习源码,也就可能变成牛逼的人.其 ...

随机推荐

  1. c++怎样让函数返回数组

    这个问题属于非常初级的问题,但是对于初学不知道的人可能会比较头疼.C++中函数是不能直接返回一个数组的,但是数组其实就是指针,所以可以让函数返回指针来实现.比如一个矩阵相乘的函数,很容易地我们就写成: ...

  2. shell简单用法笔记(一)

    一.linux中主要用的bash shell:查看linux系统中支持的shell种类可用: vim /etc/shell 执行shel脚步的方式: 1.赋予脚步可执行权限,使用相对或绝对路径调用该脚 ...

  3. 魅族M8时期写过几个app,纪念一下曾经的自己

    找工作的过程中也看了不少资料和文章,也学着别人弄弄博客,但发现自己临时的行为有点那啥吧..曾经我也写过不少东西,有过自己的一个技术论坛,为当时的魅族M8手机写过一个系列的技术帖子,但因为论坛被我关了, ...

  4. 突破瓶颈,对比学习:Eclipse开发环境与VS开发环境的调试对比

    曾经看了不少Java和Android的相关知识,不过光看不练易失忆,所以,还是写点文字,除了加强下记忆,也证明我曾经学过~~~ 突破瓶颈,对比学习: 学习一门语言,开发环境很重,对于VS的方形线条开发 ...

  5. 电子商务网站SQL注入项目实战一例

    故事A段:发现整站SQL对外输出: 有个朋友的网站,由于是外包项目,深圳某公司开发的,某天我帮他检测了一下网站相关情况. 我查看了页面源代码,发现了个惊人的事情,竟然整站打印SQL到Html里,着实吓 ...

  6. 使用EntityFramework6连接MySql数据库(db first方式)

    准备工具: VS2013.MySQL For VisualStudio 1.1.4.Connector/Net 6.8.3(百度网盘里) 程序包管理器执行命令: Install-Package Ent ...

  7. ARM汇编指令调试方法

    学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...

  8. 毫秒级的时间处理上G的图片(生成缩略图)

    测试环境: 测试图片(30M): 测试计时方法: Stopwatch sw1 = new Stopwatch(); sw1.Start(); //TODO...... sw1.Stop(); stri ...

  9. ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  10. MyBatis参数绑定规则及原理分析

    MyBatis参数的传递有几种不同的方法,本文通过测试用例出发,对其中的方式进行总结和说明,并对其部分源码进行分析. 一.测试用例(环境参考之前博客SSM接口编程一文 http://www.cnblo ...