java基础知识,字节码执行引擎

知识要点:

函数解析

静态分派

动态分派

字节码

函数解析

虚拟机方法字节码

在Java语言中符合“编译期可知,运行期不可变”。这个要求的方法,主要包括静态方法和私有方法两大类,前者与类型直接关联,后者在外部不可被访问,这两种方法各自的特点决定了它们都不可能通过继承或别的方式重写其他版本,因此它们都适合在类加载阶段进行解析。
与之相对应的是,在Java虚拟机里面提供了5条方法调用字节码指令,分别如下:

  • invokestatic 调用静态方法。
  • invokespecial 调用实例构造器<init>方法、 私有方法和父类方法。
  • invokevirtual 调用所有的虚方法。
  • invokeinterface 调用接口方法,会在运行时再确定一个实现此接口的对象。
  • invokedynamic 先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法,在此之前的4条调用指令,分派逻辑是固化在Java虚拟机内部的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

静态类型和实际类型

Human man=new Man();

上面代码中的“Human”称为变量的静态类型(Static Type),或者叫做的外观类型(Apparent Type),后面的“Man”则称为变量的实际类型(Actual Type)

虚方法

  • 非虚方法:只要能被invokestatic和invokespecial指令调用的方法,都可以在解析阶段中确定唯一的调用版本,符合这个条件的有静态方法、私有方法、实例构造器、父类方法4类。
  • 虚方法:除去final方法和非虚方法,其他方法称为虚方法

虚方法表

虚方法表(Vritual Method Table,也称为vtable,与此对应的,在invokeinterface执行时也会用到接口方法表itable)使用虚方法表索引来代替元数据查找以提高性能。虚方法表中存放着各个方法的实际入口地址。虚方法表一般是在类加载的阶段进行初始化。


  • 如果某个方法在子类中没有被重写,那子类的虚方法表里面的地址入口和父类相同方法的地址入口是一致的,都指向父类的实现入口
  • 如果子类中重写了这个方法,子类方法表中的地址将会替换为指向子类实现版本的入口地址

静态分派

所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。静态分派的典型应用是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。

public class StaticDispatch {
   static abstract class Human {
   }

   static class Man extends Human {
   }

   static class Woman extends Human {
   }

   // overload(多分派)
   public void sayHello(Human guy) {
      System.out.println("hello,guy!");
   }

   public void sayHello(Man guy) {
      System.out.println("hello,gentleman!");
   }

   public void sayHello(Woman guy) {
      System.out.println("hello,lady!");
   }


   public static void main(String[] args) {
      int i = 0;
      int m = 1;
      Human man = new Man();
      Human woman = new Woman();
      StaticDispatch sr = new StaticDispatch(); // new invokespecial
      // 下面两句函数调用是:运行时决定,还是编译时决定?
      // invokevirtual  静态分派 编译器决定
      sr.sayHello(man);     // invokevirtual
      sr.sayHello(woman);   // invokevirtual
   }
}

编译器在重载时是通过参数的静态类型而不是实际类型作为判定依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数的静态类型决定使用哪个重载版本。

动态分派

不是根据静态类型来确定,而是在运行时根据实际类型来决定函数的版本。

public class DynamicDispatch {
   static class Human {
      protected void sayHello(){
         System.out.println("Human");
      };
   }

   static class Man extends Human {
      @Override
      // 单分派
      protected void sayHello() {
         System.out.println("man say hello");
      }
   }

   static class Woman extends Human {
      @Override
      protected void sayHello() {
         System.out.println("woman say hello");
      }
   }

   public static void main(String[] args) {
      // 动态分派。不是根据静态类型来确定,而是在运行时根据实际类型来决定函数的版本。
      // 静态类型 Human man
      // 实际类型 new Man()
      Human man = new Man();       // invokespecial
      Human woman = new Woman();   // invokespecial
      man.sayHello();    // invokevirtual
      woman.sayHello();  // invokevirtual
      man = new Woman(); // new Woman
      man.sayHello();    // invokevirtual #n
   }
}

Java语言是一门静态多分派、 动态单分派的语言。

字节码

Java虚拟机的字节码指令由两部分组成

  • 操作码,也即Opcode。由一个字节长度的、 代表着某种特定操作含义的数字。由于操作码的长度只有一个字节,所以操作码总数不可能超过256条
  • 操作数,也即Operands。跟随在操作码之后的零至多个代表此操作所需参数。由于Java虚拟机采用面向操作数栈而不是寄存器架构,所以大多数的指令都不包含操作数,只有一个操作码。

字节码指令分类

  • 加法指令:iadd、 ladd、 fadd、 dadd
  • 减法指令:isub、 lsub、 fsub、 dsub
  • 乘法指令:imul、 lmul、 fmul、 dmul
  • 除法指令:idiv、 ldiv、 fdiv、 ddiv
  • 求余指令:irem、 lrem、 frem、 drem
  • 取反指令:ineg、 lneg、 fneg、 dneg
  • 位移指令:ishl、 ishr、 iushr、 lshl、 lshr、 lushr
  • 按位或指令:ior、 lor
  • 按位与指令:iand、 land
  • 按位异或指令:ixor、 lxor
  • 自增指令:iinc
  • 比较指令:dcmpg、 dcmpl、 fcmpg、 fcmpl、 lcmp
    字节码指令参考网址:adress:
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容