前言

为啥要学习JVM?

  1. 为了更好的掌握高并发编程.想要成为一个合格的高级开发或者架构师,为了应对大量请求,多线程高并发开发是必须掌握的东西.而java的多线程跟JVM有着密切的关系,为了更好的理解掌握高并发开发,必须掌握JVM知识.
  2. 为了JVM调优,GC等.不同的项目场景,对象的生命周期也不同,这就要尝试去合理分配JVM的各个内存区域的大小,以提高性能.
  3. 也可以通过JVM去了解JAVA的一些关键字(例如synchronized)的实现原理,出现问题后也好排查

    JVM是啥?

    定义:
    JVM是一种规范,Java virtual machine specifications.
    JVM的实现(比如HotSpot)可以理解为虚拟出来的一台计算机,有自己的字节码指令集(汇编语言)和内存管理(栈,堆,方法区等)
    JDK Documentation
    JVM specs11
    JRE = JVM + core lib
    JDK = JRE + development kit(一些调试工具)
    下面这张图,也有的说法讲classLoader不属于JVM,概念无所谓,领会精神即可.
    image.png
    有很多语言可以运行在JVM上
    JVM其实和java是独立的,JVM值需要class格式的文件(或文件流)
    任何语言-编译或动态生成->.class文件-运行在->JVM
    image.png

    常见的JVM的实现

    java -version就可以看到自己用的JVM的详情

  4. HotSpot:oracle官方的实现(最早是sun,后来被Oracle收购)

  5. Jrockit:BEA,曾号称世界最快JVM,被Oracle收购合并于HotSpot
  6. J9:IBM的实现
  7. Microsoft VM
  8. Alibaba Dragonwell:HotSpot深度定制版
  9. LiquidVM:直接针对硬件
  10. azul zing:垃圾回收牛批(最新业界标杆),据说很贵

    Class file format

    class文件是一个二进制的字节流;
    class文件的格式设计的特别牛批,很紧密,没有任何分隔符,得到了很多大牛的认可,所以他们设计语言时会选择翻译成class运行在JVM上
    我感觉这部分比较繁琐枯燥且平时用不到 ,很多东西先了解/记录一下,以后用得着的时候再更一步了解.
    需配合官网JVM规范第七节(java的汇编语言)一起食用.
    简单认识下编译后的class文件
    写个空类,里面啥都没有,用JDK1.8编译,我们看看它的class文件是啥样的:

EmptyClass.java:
public class EmptyClass {}
对应的class文件其实是个二进制文件,

IDEA里面查看会自动帮我们反编译

可以看到,多了个无参构造方法:
public class EmptyClass { public EmptyClass() { }}

按16进制格式打开(hexadecimal)

IntelliJ IDEA可以安装一个BinEd的插件打开;
如果用SublimeText打开的话,它是以16进制打开的:

  1. cafe babe 0000 0034 0010 0a00 0300 0d07
  2. 000e 0700 0f01 0006 3c69 6e69 743e 0100
  3. 0328 2956 0100 0443 6f64 6501 000f 4c69
  4. 6e65 4e75 6d62 6572 5461 626c 6501 0012
  5. 4c6f 6361 6c56 6172 6961 626c 6554 6162
  6. 6c65 0100 0474 6869 7301 0021 4c63 6f6d
  7. 2f65 7861 6d70 6c65 2f64 656d 6f2f 6a76
  8. 6d2f 456d 7074 7943 6c61 7373 3b01 000a
  9. 536f 7572 6365 4669 6c65 0100 0f45 6d70
  10. 7479 436c 6173 732e 6a61 7661 0c00 0400
  11. 0501 001f 636f 6d2f 6578 616d 706c 652f
  12. 6465 6d6f 2f6a 766d 2f45 6d70 7479 436c
  13. 6173 7301 0010 6a61 7661 2f6c 616e 672f
  14. 4f62 6a65 6374 0021 0002 0003 0000 0000
  15. 0001 0001 0004 0005 0001 0006 0000 002f
  16. 0001 0001 0000 0005 2ab7 0001 b100 0000
  17. 0200 0700 0000 0600 0100 0000 0700 0800
  18. 0000 0c00 0100 0000 0500 0900 0a00 0000
  19. 0100 0b00 0000 0200 0c

class file format 解读

从前到后的依次是: Magic Number, Minor version, Major version,等等,具体见下面class file规范
每个16进制的数字占4位,1个字节是8位,所以下面一个方格代表一个字节.
image.png
java的class文件的Magic Number一般都是 cafe babe
class文件版本号version,JDK7默认是51.0,JDK8默认是52.0,依次递增;51 52都是Major Version, 后面的小数位是Minor Version
有时候我们用JDK8编译的项目在JDK7的环境上跑时,会抛异常:xxxx version 52.0
后面是constant_pool_count
在后面是constant_pool_count-1个constant_pool,从#1开始,因为#0做了个预留-代表没有任何引用指向它.

显示class信息的工具

  • javap
    javap -v EmptyClass.class 输出: ```java Classfile /Users/liweizhi/IdeaProjects/msb-class/demo/target/classes/com/example/demo/jvm/EmptyClass.class Last modified 2020-3-23; size 297 bytes MD5 checksum a2e3e21cc6e7c6b5d8035663b369a23c Compiled from “EmptyClass.java” public class com.example.demo.jvm.EmptyClass minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool:

    1 = Methodref #3.#13 // java/lang/Object.”“:()V

    2 = Class #14 // com/example/demo/jvm/EmptyClass

    3 = Class #15 // java/lang/Object

    4 = Utf8

    5 = Utf8 ()V

    6 = Utf8 Code

    7 = Utf8 LineNumberTable

    8 = Utf8 LocalVariableTable

    9 = Utf8 this

    10 = Utf8 Lcom/example/demo/jvm/EmptyClass;

    11 = Utf8 SourceFile

    12 = Utf8 EmptyClass.java

    13 = NameAndType #4:#5 // ““:()V

    14 = Utf8 com/example/demo/jvm/EmptyClass

    15 = Utf8 java/lang/Object

    { public com.example.demo.jvm.EmptyClass(); descriptor: ()V flags: ACC_PUBLIC Code:
    1. stack=1, locals=1, args_size=1
    2. 0: aload_0
    3. 1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4. 4: return
    5. LineNumberTable:
    6. line 7: 0
    7. LocalVariableTable:
    8. Start Length Slot Name Signature
    9. 0 5 0 this Lcom/example/demo/jvm/EmptyClass;
    } SourceFile: “EmptyClass.java”

```

  • JBE,可以查看并修改
  • JClassLib bytecode viewer,IDEA的插件,便捷好用✅
  1. 安装插件
  2. 光标点击进入Java文件
  3. view -> Show Bytecode With jclassLib