第一节 初识JVM
JVM的概念:JVM是Java Virtual Machine的简洁。意为Java虚拟机。
虚拟机
-指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统
有哪些虚拟机
-VMWare
-Visual Box
-JVM
VMWare或者Visual Box都是使用软件模拟物理CPU的指令集
JVM使用软件模拟Java字节码的指令集
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性能
2000年JDK1.3 Hotspot 作为默认虚拟机发布 加入JavaSound
2002年JDK1.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为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优秀特性
----------------------------------------------------------------------
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的发展有积极作用
Java语言规范
-语法
-变量
-类型
-文法
JVM规范
-Class文件类型
-运行时数据
-帧栈
-虚拟机的启动
-虚拟机的指令集
语法定义
-IfThenStatement:
if(Expression)Statement if(true){do sth;}
-ArgumentList:
Argument add(a,b,c,d);
ArgumentList,Argument
词法结构
- \u + 4个16进制数字 表示UTF-16
- 行终结符:CR,or LF,or CR LF。
- 空白符
空格 tab \t 换页 \f 行终结符
- 注释
- 标示符
- 关键字
------------------------------------------------------------------------
- public static void 打印(){
- System.out.println("中文方法哦");
- }
- public static void main(String[] args){
- 打印();
- }
-----------------------------------------------------------------------
词法结构
- Int
0 2 0372 0xData_Cafe 1996 0x00_FF__00_FF
- Long
0|0777L 0x100000000L 2_147_483_648L 0xC0B0L
- Float
le1f 2.f .3f 0f 3.14f 6.022137e+23f
- Double
le1 2. .3 0.0 3.14 1e-9d 1e137
- 操作
+= -= *= /= &= |= ^= %= <<= >>= >>>=
----------------------------------------------------------------------
哪些是合法的数字呢?
- private int a = 0xDada_Cafe;
- private float b = 0x1.fffffeP + 127f;
- private float c = 1996;
- private float d = 1996.3;
- private int f = 9999e2;
- private double g = 33e2;
- private float h = 0x1.fffep-12f;
- private float i = 1.fffep-12f;
- private long p = 0b1_1_1_0_1;
- private long q = 0b1_1_1_0_2;
类型和变量
-元类型
byte short int long float char
-变量初始值
boolean false
char\u0000
-泛型
class Value{int val;}
class Test{
public static void main(String[] args){
int i1 = 3;
int i2 = i1;
i2 = 4;
System.out.print("i1==" + i1);
System.out.println("but i2==" + i2);
Value v1 = new Value();
v1.val = 5;
Value v2 =v1;
v2.val = 6;
System.out.print("v1.val==" + v1.val);
System.out.println("and v2.val==" + v2.val);
}
}
i1==3 but i2==4
v1.val==6 and v2.val==6
i1 i2为不同的变量
v1 v2为引用同一个实例
------------------------------------------------------------
Java内存模型
类加载链接过程
public static final abstract 的定义
异常
数组的使用
Java语言规范定义了什么是Java语言
Java语言和JVM相对独立
-Groovy
-Clojure
-Scala
JVM主要定义二进制class文件和JVM指令集等
------------------------------------------------------------------
JVM规范
Class文件格式
数字的内部表示和存储
-Byte -128 to 127(-2 * 7 to 2 * 7 -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);
}
----------------------------------------------------------------------
5
000000101
-6
原码:10000110
反码:11111001
补码:11111010
-1
原码:10000001
反码:11111110
补码:11111111
-----------------------------------------------------------------
为什么要用补码?
-计算0的表示:
0
正数:00000000
负数:10000000
0
正数:00000000
0
负数:1000000
反码:1111111
补码:0000000
-6+5
11111010
+00000101
=11111111
-4+5
11111100
+00000101
=00000001
-3+5
11111101
+00000101
=00000010
-------------------------------------------------------------------
Float的表示与定义
-支持IEEE 754
$eeeeeeee mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
指数 8 尾数:23
e全0尾数附加位为0 否则尾数附加位为1
e全0 尾数附加位为0 否则尾数附加位为1
s*m*2^(e-127)
一些特殊的方法
-<clinit>
-<init>
-----------------------------------------------------------------
VM指令集
-类型转化
l2i
出栈入栈操作
aload astore
运算
iadd isub
流程控制
ifeq ifne
函数调用
invokevirtual invokeinterface invokespecial invokestatic
----------------------------------------------------------------------
JVM需要对Java Library提供以下支持:
-反射java.lang.reflect
-ClassLoader
-初始化class和interface
-安全相关 java.secuirty
-多线程
-弱引用
---------------------------------------------------------------------
JVM的编译
-源码到JVM指令的对应格式
-Javap
-JVM反汇编的格式
<index><opcode>[<operand1>[<operand2>...]][comment]
void spin(){
int i;
for(i=0;i<100;i++){;
//Loop body is empty
}
}
0 iconst_0 //Push int constant 0
1 istore_1 //Store into local variable 1(i=0)
2 goto 8 //First time through don't increment
5 iinc 1 1 //Increment local variable 1 by 1(i++)
8 iload_1 //Push local variable 1(i)
9 bipush 100 //Push int constant 100
11 if_icmplt 5 //Compare and loop if less than (i<100)
14 return //Return void when done
-------------------------------------------------------没有规矩 不成方圆-----------------
第二节 JVM运行机制
JVM启动流程
------------------------------------------------------------------------------------------------
Java XXX--->装载配置--->根据配置寻找JVM.dll--->初始化JVM获得JNIEnv接口--->找到main方法并运行
| | |
| | |
根据当前路径和系统版本寻找 | |
jvm.cfg | |
JVM.dll为JVM主要实现 |
JNIEnv为JVM接口,findClass等操作通过它实现
----------------------------------------------------------------------------------------------------
JVM基本结构
内存模型
编译和解释运行的概念
PC寄存器
-每个线程拥有一个PC寄存器
-在线程创建时 创建
-指向下一个指令的地址
-执行本地方法时,PC的值为undefined
-----------------------------------------------------------------------------------
方法区
-保存装载的类信息
类型的常量池
字段、方法信息
方法字节码
-通常和永久区(Perm)关联在一起
JDK6时,String等常量信息置于方法
JDK7时,已经移动到了堆
------------------------------
Java堆
-和程序开发密切相关
-应用系统对象都保存在Java堆中
-所有线程共享Java堆
-对分代GC来说,堆也是分代的
-GC的主要工作区间
|------------------------------------|
|eden s0 s1 tenured |
|------------------------------------|
复制算法
Java栈
-线程私有
-栈由一系列帧组成(因此Java栈也叫做帧栈)
-帧保存一个方法的局部变量、操作数栈、常量池指针
-每一个方法调用创建一个帧,并压栈
Java栈-局部变量表 包含参数和局部变量
public class StackDemo{
public static int runStatic(int i,long l,float f,Object o,byte b){
return 0;
}
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
--------
public int runInstance(char c,short s,boolean b){
return 0;
}
}
0 reference this
1 int char c
2 int shourt s
3 int boolean b
----------------------
Java栈-函数调用组成帧栈
public static int runStatic(int i,long l,float f,Object o,byte b){
return runStatic(i,l,f,o,b);
}
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
注释:这是一个帧 省略:操作数栈 返回地址等
-----------------------------------------------
Java栈-操作数栈
-Java没有寄存器,所有参数传递使用操作数栈
public static int add(int a,int b){
int c = 0;
c = a + b;
return c;
}
0:iconst_0 //压栈
1:istore_2 //弹出int,存放于局部变量2
2:iload_0 //把局部变量0压栈
3:il0ad_1 //局部变量1压栈
4:iadd //弹出2个变量,求和,结果压栈
5:istore_2 //弹出结果,放于局部变量2
6:iload_2 //局部变量2压栈
7:ireturn //返回
---------------------------------
Java栈-栈上分配
C++代码示例
class BcmBasicString{ ...}
public void method(){
BcmBasicString* str = new BcmBasicString;
... delete str;
}
public void method(){
BcmBasicString str;
...
}
-小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
-直接分配在栈上,可以自动回收,减轻GC压力
-大对象或者逃逸对象无法栈上分配
-----------------------------
解释运行
-解释执行以解释方式运行字节码
-解释执行的意思是:读一句执行一句
编译运行(JIT)
-将字节码编译成机器码
-直接执行机器码
-运行时编译
-编译后性能有数量级的提升
----------------------知己知彼 百战不殆--------------------------
JVM种类
JVM规范
JVM的概念:JVM是Java Virtual Machine的简洁。意为Java虚拟机。
虚拟机
-指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统
有哪些虚拟机
-VMWare
-Visual Box
-JVM
VMWare或者Visual Box都是使用软件模拟物理CPU的指令集
JVM使用软件模拟Java字节码的指令集
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性能
2000年JDK1.3 Hotspot 作为默认虚拟机发布 加入JavaSound
2002年JDK1.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为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优秀特性
----------------------------------------------------------------------
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的发展有积极作用
Java语言规范
-语法
-变量
-类型
-文法
JVM规范
-Class文件类型
-运行时数据
-帧栈
-虚拟机的启动
-虚拟机的指令集
语法定义
-IfThenStatement:
if(Expression)Statement if(true){do sth;}
-ArgumentList:
Argument add(a,b,c,d);
ArgumentList,Argument
词法结构
- \u + 4个16进制数字 表示UTF-16
- 行终结符:CR,or LF,or CR LF。
- 空白符
空格 tab \t 换页 \f 行终结符
- 注释
- 标示符
- 关键字
------------------------------------------------------------------------
- public static void 打印(){
- System.out.println("中文方法哦");
- }
- public static void main(String[] args){
- 打印();
- }
-----------------------------------------------------------------------
词法结构
- Int
0 2 0372 0xData_Cafe 1996 0x00_FF__00_FF
- Long
0|0777L 0x100000000L 2_147_483_648L 0xC0B0L
- Float
le1f 2.f .3f 0f 3.14f 6.022137e+23f
- Double
le1 2. .3 0.0 3.14 1e-9d 1e137
- 操作
+= -= *= /= &= |= ^= %= <<= >>= >>>=
----------------------------------------------------------------------
哪些是合法的数字呢?
- private int a = 0xDada_Cafe;
- private float b = 0x1.fffffeP + 127f;
- private float c = 1996;
- private float d = 1996.3;
- private int f = 9999e2;
- private double g = 33e2;
- private float h = 0x1.fffep-12f;
- private float i = 1.fffep-12f;
- private long p = 0b1_1_1_0_1;
- private long q = 0b1_1_1_0_2;
类型和变量
-元类型
byte short int long float char
-变量初始值
boolean false
char\u0000
-泛型
class Value{int val;}
class Test{
public static void main(String[] args){
int i1 = 3;
int i2 = i1;
i2 = 4;
System.out.print("i1==" + i1);
System.out.println("but i2==" + i2);
Value v1 = new Value();
v1.val = 5;
Value v2 =v1;
v2.val = 6;
System.out.print("v1.val==" + v1.val);
System.out.println("and v2.val==" + v2.val);
}
}
i1==3 but i2==4
v1.val==6 and v2.val==6
i1 i2为不同的变量
v1 v2为引用同一个实例
------------------------------------------------------------
Java内存模型
类加载链接过程
public static final abstract 的定义
异常
数组的使用
Java语言规范定义了什么是Java语言
Java语言和JVM相对独立
-Groovy
-Clojure
-Scala
JVM主要定义二进制class文件和JVM指令集等
------------------------------------------------------------------
JVM规范
Class文件格式
数字的内部表示和存储
-Byte -128 to 127(-2 * 7 to 2 * 7 -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);
}
----------------------------------------------------------------------
5
000000101
-6
原码:10000110
反码:11111001
补码:11111010
-1
原码:10000001
反码:11111110
补码:11111111
-----------------------------------------------------------------
为什么要用补码?
-计算0的表示:
0
正数:00000000
负数:10000000
0
正数:00000000
0
负数:1000000
反码:1111111
补码:0000000
-6+5
11111010
+00000101
=11111111
-4+5
11111100
+00000101
=00000001
-3+5
11111101
+00000101
=00000010
-------------------------------------------------------------------
Float的表示与定义
-支持IEEE 754
$eeeeeeee mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
指数 8 尾数:23
e全0尾数附加位为0 否则尾数附加位为1
e全0 尾数附加位为0 否则尾数附加位为1
s*m*2^(e-127)
一些特殊的方法
-<clinit>
-<init>
-----------------------------------------------------------------
VM指令集
-类型转化
l2i
出栈入栈操作
aload astore
运算
iadd isub
流程控制
ifeq ifne
函数调用
invokevirtual invokeinterface invokespecial invokestatic
----------------------------------------------------------------------
JVM需要对Java Library提供以下支持:
-反射java.lang.reflect
-ClassLoader
-初始化class和interface
-安全相关 java.secuirty
-多线程
-弱引用
---------------------------------------------------------------------
JVM的编译
-源码到JVM指令的对应格式
-Javap
-JVM反汇编的格式
<index><opcode>[<operand1>[<operand2>...]][comment]
void spin(){
int i;
for(i=0;i<100;i++){;
//Loop body is empty
}
}
0 iconst_0 //Push int constant 0
1 istore_1 //Store into local variable 1(i=0)
2 goto 8 //First time through don't increment
5 iinc 1 1 //Increment local variable 1 by 1(i++)
8 iload_1 //Push local variable 1(i)
9 bipush 100 //Push int constant 100
11 if_icmplt 5 //Compare and loop if less than (i<100)
14 return //Return void when done
-------------------------------------------------------没有规矩 不成方圆-----------------
第二节 JVM运行机制
JVM启动流程
------------------------------------------------------------------------------------------------
Java XXX--->装载配置--->根据配置寻找JVM.dll--->初始化JVM获得JNIEnv接口--->找到main方法并运行
| | |
| | |
根据当前路径和系统版本寻找 | |
jvm.cfg | |
JVM.dll为JVM主要实现 |
JNIEnv为JVM接口,findClass等操作通过它实现
----------------------------------------------------------------------------------------------------
JVM基本结构
内存模型
编译和解释运行的概念
PC寄存器
-每个线程拥有一个PC寄存器
-在线程创建时 创建
-指向下一个指令的地址
-执行本地方法时,PC的值为undefined
-----------------------------------------------------------------------------------
方法区
-保存装载的类信息
类型的常量池
字段、方法信息
方法字节码
-通常和永久区(Perm)关联在一起
JDK6时,String等常量信息置于方法
JDK7时,已经移动到了堆
------------------------------
Java堆
-和程序开发密切相关
-应用系统对象都保存在Java堆中
-所有线程共享Java堆
-对分代GC来说,堆也是分代的
-GC的主要工作区间
|------------------------------------|
|eden s0 s1 tenured |
|------------------------------------|
复制算法
Java栈
-线程私有
-栈由一系列帧组成(因此Java栈也叫做帧栈)
-帧保存一个方法的局部变量、操作数栈、常量池指针
-每一个方法调用创建一个帧,并压栈
Java栈-局部变量表 包含参数和局部变量
public class StackDemo{
public static int runStatic(int i,long l,float f,Object o,byte b){
return 0;
}
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
--------
public int runInstance(char c,short s,boolean b){
return 0;
}
}
0 reference this
1 int char c
2 int shourt s
3 int boolean b
----------------------
Java栈-函数调用组成帧栈
public static int runStatic(int i,long l,float f,Object o,byte b){
return runStatic(i,l,f,o,b);
}
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
0 int int i
1 long long l
3 float float f
4 reference Object o
5 int byte b
注释:这是一个帧 省略:操作数栈 返回地址等
-----------------------------------------------
Java栈-操作数栈
-Java没有寄存器,所有参数传递使用操作数栈
public static int add(int a,int b){
int c = 0;
c = a + b;
return c;
}
0:iconst_0 //压栈
1:istore_2 //弹出int,存放于局部变量2
2:iload_0 //把局部变量0压栈
3:il0ad_1 //局部变量1压栈
4:iadd //弹出2个变量,求和,结果压栈
5:istore_2 //弹出结果,放于局部变量2
6:iload_2 //局部变量2压栈
7:ireturn //返回
---------------------------------
Java栈-栈上分配
C++代码示例
class BcmBasicString{ ...}
public void method(){
BcmBasicString* str = new BcmBasicString;
... delete str;
}
public void method(){
BcmBasicString str;
...
}
-小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
-直接分配在栈上,可以自动回收,减轻GC压力
-大对象或者逃逸对象无法栈上分配
-----------------------------
解释运行
-解释执行以解释方式运行字节码
-解释执行的意思是:读一句执行一句
编译运行(JIT)
-将字节码编译成机器码
-直接执行机器码
-运行时编译
-编译后性能有数量级的提升
----------------------知己知彼 百战不殆--------------------------
JVM种类
JVM规范