JVM深入虚拟机系列1-----初识JVM及JVM运行原理

一 初识JVM

  • 一.1.JVM的概念
  • 一.2.JVM发展历史
  • 一.3.JVM种类
  • 一.4.Java语言规范
  • 一.5.JVM规范

二 JVM运行原理

  • 1.JVM启动流程
  • 2.JVM基本结构
  • 3.内存模型
  • 4.编译和解释运行的概念

1.JVM的概念

JVM是Java Virtual Machine的简称。意为Java虚拟机 虚拟机:指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统. 有哪些虚拟机: VMWare Visual Box JVM VMWare或者Visual Box都是使用软件模拟物理CPU的指令集(硬盘内存都是真实存在的) JVM使用软件模拟Java 字节码的指令集(虚拟的虚拟机)

2.JVM发展历史

1996年 SUN JDK 1.0 Classic VM: 纯解释运行,使用外挂进行JIT 1997年 JDK1.1 发布: ---AWT、内部类、JDBC、RMI、反射 1998年 JDK1.2 Solaris Exact VM --- JIT 解释器混合 --- Accurate Memory Management 精确内存管理,数据类型敏感 --- 提升的GC性能 (JDK1.2开始 称为Java 2J2SE J2EE J2ME 的出现加入Swing Collections )

2000年 JDK 1.3 Hotspot 作为默认虚拟机发布(加入JavaSound
)
2002年 JDK 1.4 Classic VM退出历史舞台(Assert 正则表达式 NIO IPV6 日志API 加密类库
)
2004年发布 JDK1.5 即 JDK5 、J2SE 5 、Java 5
— 泛型
— 注解
— 装箱
— 枚举
— 可变长的参数
— Foreach循环
JDK1.6 JDK6
— 脚本语言支持
— JDBC 4.0
— Java编译器 API
2011年 JDK7发布
— 延误项目推出到JDK8
— G1
— 动态语言增强
— 64位系统中的压缩指针
— NIO 2.0
2014年 JDK8发布
— Lambda表达式
— 语法增强 Java类型注解
— 2016年JDK9
— 模块化
JVM-Java和JVM的大事记
使用最为广泛的JVM为HotSpot
HotSpot 为Longview Technologies开发 被SUN收购
2006年 Java开源 并建立OpenJDK
— HotSpot 成为Sun JDK和OpenJDK中所带的虚拟机
2008 年 Oracle收购BEA
— 得到JRockit VM
2010年Oracle 收购 Sun
— 得到Hotspot
Oracle宣布在JDK8时整合JRockit和Hotspot,优势互补
— 在Hotspot基础上,移植JRockit优秀特性

3.JVM种类

KVM
— SUN发布
— IOS Android前,广泛用于手机系统
CDC/CLDC HotSpot
— 手机、电子书、PDA等设备上建立统一的Java编程接口
— J2ME的重要组成部分
JRockit
— BEA
IBM J9 VM
— IBM内部使用
Apache Harmony
—兼容于JDK 1.5和JDK 1.6的Java程序运行平台
—与Oracle关系恶劣 退出JCP ,Java社区的分裂
—OpenJDK出现后,受到挑战 2011年 退役
—没有大规模商用经历
—对Android的发展有积极作用

4.Java语言规范

Java语言规范
— 语法
— 变量
— 类型
— 文法

  1. 语法定义:

    if(true){do sth;}
    add(a,b,c,d);

  2. 词法结构
    — \u + 4个16进制数字 表示UTF-16
    — 行终结符: CR, or LF, or CR LF.
    — 空白符
    . 空格 tab \t 换页 \f 行终结符
    — 标示符
    — 关键字
    Int:
    —0 2 0372 0xDada_Cafe 1996 0x00_FF__00_FF
    Long:
    —0l 0777L 0x100000000L 2_147_483_648L 0xC0B0L
    Float:
    —1e1f 2.f .3f 0f 3.14f 6.022137e+23f
    Double:
    —1e1 2. .3 0.0 3.14 1e-9d 1e137
    操作:
    — += -= *= /= &= |= ^= %= <<= >>= >>>=

  3. 类型和变量
    元类型:
    byte short int long float char
    变量初始值:
    boolean false
    char \u0000
    泛型:

  4. Java内存模型

  5. 类加载链接的过程

  6. public static final abstract的定义

  7. 异常

  8. 数组的使用
    …….

5.JVM规范

Java语言规范定义了什么是Java语言
Java语言和JVM相对独立
Groovy Clojure Scala这些语言也能在JVM上运行
JVM主要定义二进制class文件和JVM指令集等

  • Class 文件格式
  • 数字的内部表示和存储
  • Byte -128 to 127 (-27 to 27 - 1)
  • returnAddress 数据类型定义
  • 指向操作码的指针。不对应Java数据类型,不能在运行时修改。Finally实现需要
  • 定义PC
  • 方法区
    整数的表达
    原码:第一位为符号位(0为正数,1为负数)
    反码:符号位不动,原码取反
    负数补码:符号位不动,反码加1
    正数补码:和原码相同
    打印整数的二进制表示
    int a=-6;
    for(int i=0;i<32;i++){
    int t=(a & 0x80000000>>>i)>>>(31-i);
    System.out.print(t);
    }
    例:-6
    原码: 10000110
    反码: 11111001
    补码: 11111010
    -1
    原码: 10000001
    反码: 11111110
    补码: 11111111
    为什么要用补码?
    0
    正数:00000000
    负数:10000000
    0
    正数(补码):00000000
    0
    负数:10000000
    反码:11111111
    补码:00000000
    Float的表示与定义
    支持 IEEE 754
    s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
    指数:8 尾数:23
    e全0 尾数附加位为0 否则尾数附加位为1
    sm2^(e-127)
    -5
    11000000101000000000000000000000
    -1*2(129-127)*(20+2^-2)
    一些特殊的方法
    < clinit>
    < init>
    VM指令集
    类型转化
    — l2i
    出栈入栈操作
    — aload astore
    运算
    — iadd isub
    流程控制(=和!=)
    — ifeq ifne
    函数调用 调用接口 静态…
    — invokevirtual invokeinterface invokespecial invokestatic
    JVM需要对Java Library 提供以下支持:
    反射 java.lang.reflect
    ClassLoader
    初始化class和interface
    安全相关 java.security
    多线程
    弱引用
    JVM的编译
    源码到JVM指令的对应格式
    Javap
    JVM反汇编的格式
  • < index> < opcode> [ < operand1> [ < operand2>… ]] [< comment > ]

二.JVM运行原理

1.JVM启动流程

JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第1张图片

2.JVM基本结构

JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第2张图片

PC寄存器:

  • 每个线程拥有一个PC寄存器
  • 在线程创建时 创建
  • 指向下一条指令的地址
  • 执行本地方法时,PC的值为undefined

方法区:
1.保存装载的类信息:

  • 类型的常量池
  • 字段,方法信息
  • 方法字节码

2.通常和永久区(Perm)关联在一起(JDK6时,String等常量信息置于方法JDK7时,已经移动到了堆)
Java堆

  • 和程序开发密切相关
  • 应用系统对象都保存在Java堆中
  • 所有线程共享Java堆
  • 对分代GC来说,堆也是分代的
  • GC的主要工作区间

Java栈

  • 线程私有
  • 栈由一系列帧组成(因此Java栈也叫做帧栈)
  • 帧保存一个方法的局部变量、操作数栈、常量池指针
  • 每一次方法调用创建一个帧,并压栈

栈实例:
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第3张图片
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第4张图片
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第5张图片
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第6张图片

JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第7张图片
Java栈总结 – 栈上分配

  • 小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
  • 直接分配在栈上,可以自动回收,减轻GC压力
  • 大对象或者逃逸对象无法栈上分配

栈、堆、方法区交互
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第8张图片

3.内存模型

JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第9张图片
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第10张图片
JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第11张图片
可见性:一个线程修改了变量,其他线程可以立即知道
保证可见性的方法:

  1. volatile
  2. synchronized (unlock之前,写变量值回主存)
  3. final(一旦初始化完成,其他线程就可见)

有序性:

  1. 在本线程内,操作都是有序的
  2. 在线程外观察,操作都是无序的。(指令重排 或 主内存同步延时)

指令重排:

  1. 线程内串行语义:
    写后读 a = 1;b = a; 写一个变量之后,再读这个位置。
    写后写 a = 1;a = 2; 写一个变量之后,再写这个变量。
    读后写 a = b;b = 1; 读一个变量之后,再写这个变量。
    以上语句不可重排
    编译器不考虑多线程间的语义
    可重排: a=1;b=2;

JVM深入虚拟机系列1-----初识JVM及JVM运行原理_第12张图片
指令重排的基本原则:

  • 程序顺序原则:一个线程内保证语义的串行性
  • volatile规则:volatile变量的写,先发生于读
  • 锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
  • 传递性:A先于B,B先于C 那么A必然先于C
  • 线程的start方法先于它的每一个动作
  • 线程的所有操作先于线程的终结(Thread.join())
  • 线程的中断(interrupt())先于被中断线程的代码
  • 对象的构造函数执行结束先于finalize()方法

4.编译和解释运行的概念

解释运行:
解释执行以解释方式运行字节码
解释执行的意思是:读一句执行一句
编译运行(JIT):
将字节码编译成机器码
直接执行机器码
运行时编译
编译后性能有数量级的提升

你可能感兴趣的:(JVM深入虚拟机系列1-----初识JVM及JVM运行原理)