JVM原理【学习中】

基础概念

1. 常用操作

1.1. 查看字节码(反编译)

javap -v xxx.class 

2. 虚拟机分类

系统虚拟机:模拟硬件环境,是对物理计算机的仿真。比如VirtualBox,VMware

程序虚拟机:为执行单个程序而设计。比如JVM

3. 解释器与即时编译器

解释器直接运行,响应时间短,但是执行速度慢

即时编译器需要一段时间准备后才能运行,响应长,但是执行速度快

JVM混合使用二者

4. JVM历史(精简)

4.1. Sun Classic VM

  • 世界上第一款商用JVM,由Sun公司在1996年和Java1.0一同发布,JDK1.4时被淘汰
  • JVM内部只提供解释器
  • 只能通过外挂方式使用JIT,而且解释器不能和JIT协同工作(二者只能用一个)

4.2. Exact VM

  • Sun在Java1.2时短暂使用过
  • 准确式内存管理,JVM可以知道内存某处的数据具体是什么类型(值还是地址)
  • 可以热点探测;可以让编译器和解释器混合工作

4.3. HotSpot VM

  • JDK1.3开始成为Java默认虚拟机
  • 市场定位是多用途的

4.4. JRockit

  • 专注于服务器端
  • 不关注启动速度,所以不包含解释器,全靠即时编译,所以JRockit是世界上最快的JVM

4.5. J9

全称IBM Technology for JVM,简称IT4J,内部代号是J9。

市场定位也是多用途

4.6. TaobaoJVM

基于OpenJDK HotSpot VM,深度定制并开源

  • GCIH,off-heap

4.7. Davik VM

  • Android的虚拟机
  • 它没有遵循JVM规范:1. 指令架构采用寄存器架构 2. 字节码不是.class文件不是.dex
  • Android5.0后被Art VM(支持提前编译,AOT)替换

5. 三大主流JVM

JVM的3种主流实现:

HotSpot(JDK默认JVM),Sun(已被Oracle收购)开发的

JRockit,BEA(已被Oracle收购)开发的

J9,IBM开发的(已开源)

6. JVM指令架构模型

JVM接收的指令流(字节码内容)有两种,一种是基于栈的指令集架构,一种是基于寄存器的指令集架构

典型例子 指令集特点 跨平台
基于栈的指令集 HotSpot用的指令集 1. 大部分是0地址指令(避开了寄存器的分配难题,实现简单)
2. 指令集更小;完成操作所用的指令更多(1个2+3的操作,需要9条指令);性能更差
不依赖硬件,可以跨平台
基于寄存器的指令集 PC的x86,Android的Davlik 1.大部分多地址指令
2.指令集更大;完成一个操作,所用的指令更少(同样的2+3只需要2条指令);性能更高
依赖硬件,跨平台差

7. JVM的生命周期

7.1. 启动

引导类加载器(Bootstrap Class Loader)加载一个初始类(initial class)完成JVM的启动。至于初始类是什么,这是由虚拟机的具体实现决定的

7.2. 执行

Java程序开始运行时JVM才运行,Java程序结束时JVM就停止。执行一个Java程序实际上是在执行一个叫做JVM的进程

打印当前运行的Java进程

jps

7.3. 退出

有以下几种情况:

  1. 程序正常结束
  2. 程序因为异常或错误结束
  3. OS出错导致JVM进程结束
  4. 程序调用System.exit(), Runtime.exit(), Runtime.halt()方法结束自己
  5. JNI中的API

JVM概览

JVM概览

1. 类加载器子系统

类加载子系统

  1. 加载 Loading 把字节码文件数据读入内存
  2. 链接 Linking
  3. 初始化 Initialization 给静态变量赋初值

2. 运行时数据区

JVM管理内存的结构

运行时数据区

  1. 方法区 Method Area 类的信息,比如静态变量,常量
  2. 堆区 Heap Area 所有对象实体
  3. 每个线程一份的
    1. 程序计数器 PC Registers
    2. JVM栈区 Stack Area
    3. 本地方法栈 Native Method Stack

3. 执行引擎

执行引擎

  1. 解释器:逐行把字节码翻译成机器指令
  2. JIT:把热点代码的字节码翻译成机器指令存起来
  3. 垃圾回收器

类加载器

负责从文件系统或者网络中加载.class文件到内存中, 至于它能否运行由执行引擎决定

1. 加载

  1. 通过类的全限定名获取此类的二进制字节流
    • 加载.class文件有很多途径
  2. 把字节流所代表的静态存储结构转化成方法区的运行时数据结构
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区中这个类的各种数据的访问入口

2. 链接

2.1. 验证

检测字节流中的信息是否符合当前JVM的要求(CA FE BA BE开头),是否会危害JVM自身的安全
字节码内容

2.2. 准备

为类变量(static)分配内存,并且设置类变量的初始值,即“零值”
常量(static final)在编译时已经分配内存和赋零值了,它在准备阶段进行真的初始化

2.3. 解析

把符号引用转换位直接引用。 下图中所圈的就时符号引用,在解析时会把它们换成对应字节码文件的地址

符号引用

内存管理与GC

性能监控与调优

posted @ 2020-06-11 06:49  Leonuoa7  阅读(93)  评论(0编辑  收藏  举报