2. JVM基础

1 java从编码到执行

2. JVM基础

2 从跨平台到跨语言
  1. jvm相当于虚构出来的一个计算机,有自己的字节码指令集,即自己的汇编语言,也有自己的内存管理方案:栈、堆、方法区
  2. jvm跟java语言无关,跟class有关,只要语言能编译成class,jvm就能执行
  3. jvm是一种规范,调优是针对这个规范的来具体实现
  4. 常见的jvm实现
    1. HotSpot:Oracle公司
    2. Jrockit:已与HotSpot合并
    3. J9:IBM公司
    4. Microsoft VM
    5. TaobaoVM:hotspot深度定制版
    6. Liquid VM:直接针对硬件
    7. zing:azul公司,很贵,垃圾回收快,业界标杆,ZGC就是参考的zing里的实现
  5. 所谓的java8以后都收费,是虚拟机收费,而不是java语言本身收费,我们可以使用openjdk、TablBaoVM,这些内涵开源的hotspot版本的jdk,免费使用
  6. jdk、jre、jvm间关系
    1. jdk = jre+development kit
      1. development kit包括一些调试的工具,jdk目录里,除了jre,都是jdk的内容
    2. jre = jvm+core lib
    3. jvm
3 翻译.class文件

2. JVM基础

  1. 可以使用sublime、notepad、Intellij的BinEd,将.class文件以16进制码或2进制码打开
    1. BinEd:File–Open As Binary,选项Binary为二进制显式,HEX为16进制
  2. 这个二进制字节流,是由java虚拟机进行解释
  3. 字节流中的数据类型
    1. u1:1个字节的无符号整数,1个字节应该是8位二进制数,也就是2位的16进制数
    2. u2:2字节
    3. u4:4字节
    4. u8:8字节
    5. _info:表类型,是hotspot源码中的写法
  4. 几个位置字节的含义
    1. 1-4字节:Magic Number,CA FE BA BE:表示文件类型为javac编译的class文件
    2. 5-8字节:表示版本号,2个字节的Minor Version小版本号+2字节的Major Version大版本号,java1.8对应的大版本号值就是十六进制的0034,即52
    3. 9-10字节:constant_pool_count,表示常量池中有多少内容,由于占用2个字节,因此最多存放2的16次方个常量,但由于常量池中,预留了一位不允许使用,因此常量池实际上可以存放constant_pool_count-1个常量
    4. constant_pool:长度为constant_pool_count-1的一张表(数组),编号从1 开始,0号做了预留,里面内容特别繁琐
    5. access_flags:修饰class的一些关键字,使用按位或运算,例如0x0421,表示0x0001(public)|0x0020(invokespectial为真)|0x0400(abstract),也就是说,该类由public abstract修饰
    6. this_class:当前的class,是常量池中的哪个常量表示
    7. supper_class:
    8. interfaces_count
    9. interfaces
    10. fields_count
    11. fields
    12. methods_count
    13. methods
    14. attributes_count
    15. attributes
  5. 直接看二进制或十六进制码过于费劲,可以使用工具对class中内容进行翻译
    1. javap -v class位置
    2. JBE:java bytecode editor可以直接修改二进制码
    3. JClass-Lib:IDEA插件,安装好后,鼠标点进class里,view–Show bytecode with jclasslib
      2. JVM基础
      2. JVM基础
  6. 每一个常量,第1个字节都表示常量的类型,从1到18分别有不同的含义
    1. CONSTANT_Utf8_info:可以理解为一个utf8编码格式的字符对象
    2. CONSTANT_Methodref_info:可以理解为一个存放方法引用信息的对象,该对象中含有两个引用,这两个引用通过二进制码0002与000D所表示的常量池中的第2和第13个常量,即一个指向表示当前方法所在类的CONSTANT_Class_info对象,另一个指向表示方法名和类型的CONSTANT_NameAndType对象
    3. CONSTANT_NamedAndType_info:该对象也包含两个引用,一个指向第4个表示方法名的CONSTANT_Utf8_info对象,一个指向第5个表示方法返回值的CONSTANT_Utf8_info对象。其中<init>表示该方法为初始化方法,<()V>表示该方法无参,且返回值为void
    4. 具体(V)表示的含义,可以参考图中methods-descriptor_index中的解释,以及fields-descriptor_index中的解释,注意该图中涉及到index,都表示在常量值中的元素位置
      2. JVM基础
  7. methods中会有一些附加属性,而Code属性是其中最重要的那个,表示代码是怎么实现的,比如对于该方法,字节码指令为2ab70001b1,JVM将2a转为JVM中为汇编指令aload_0,表示将方法局部变量表中第0项(this),扔到操作数栈中,然后将b7转为invokespecial,表示调用this的构造方法,然后将这个方法后面4位0001所指向常量池中第一个常量的构造方法,为Object构造方法,进行调用,所以创建对象前,会先调用父类构造器。最后JVM将这些指令一条条的执行
  8. java指令集最多有256个,指令可以在java虚拟机规范文档中,找到对应的含义