JVM内核-原理、诊断与优化学习笔记(一):初识JVM
文章目录
- JVM的概念
- JVM是Java Virtual Machine的简称。意为Java虚拟机
- 虚拟机
- 有哪些虚拟机
- VMWare或者Visual Box都是使用软件模拟物理CPU的指令集
- JVM使用软件模拟Java 字节码的指令集
- JVM发展历史
- 1996年 SUN JDK 1.0 Classic VM
- 1997年 JDK1.1 发布
- 1998年 JDK1.2 Solaris Exact VM
- 2000年 JDK 1.3 Hotspot 作为默认虚拟机发布
- 2002年 JDK 1.4 Classic VM退出历史舞台
- 2004年发布 JDK1.5 即 JDK5 、J2SE 5 、Java 5(重要版本)
- JDK1.6 JDK6
- 2011年 JDK7发布
- 2014年 JDK8发布(重要版本)
- 2016年JDK9
- 大事件
- JVM种类
- Java语言规范
- JVM规范
JVM的概念
JVM是Java Virtual Machine的简称。意为Java虚拟机
虚拟机
指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统
有哪些虚拟机
- VMWare
- Visual Box
- JVM
VMWare或者Visual Box都是使用软件模拟物理CPU的指令集
比如它们模拟的cpu、硬盘、内存,等都是现实存在的,能够在现实中找到对应的案例的。
JVM使用软件模拟Java 字节码的指令集
JVM模拟的对象是现实中没有的,现实中没有任何一个计算机能够运行Java字节码,单纯从从软件上做的一个设计,来模拟一个硬件的行为,比如jvm运行的的是java字节码指令集,为了设计上的精简,我们知道正常的cpu中有若干个寄存器,jvm中除了pc寄存器外,其他的寄存器都做了裁剪,因为寄存器的主要功能是加快数据访问的速度,因为在jvm中是纯粹用软件模拟的,速度使用寄存器后并不会有很好的提升,并且引入寄存器后,也为jvm的设计以及实现带来很大的困难,所以把这些功能去掉了。综上,jvm是一个被定制过的现实中不存在的计算机。
JVM发展历史
1996年 SUN JDK 1.0 Classic VM
纯解释运行,使用外挂进行JIT,没有内置的即时编译的模块,一旦开启外挂,解释运行的功能就没有了。
Classic VM生命周期比较长,在1.3 、1.4的时候才被淘汰
1997年 JDK1.1 发布
-AWT、内部类、JDBC、RMI、反射
1998年 JDK1.2 Solaris Exact VM
JIT 解释器混合
Accurate Memory Management 精确内存管理,数据类型敏感
提升的GC性能
JDK1.2开始 称为Java 2
J2SE J2EE J2ME 的出现
加入Swing Collections
Solaris Exact VM生命周期比较短。
2000年 JDK 1.3 Hotspot 作为默认虚拟机发布
加入JavaSound加入了一些声音上的api
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(开放了这个API)
2011年 JDK7发布
延误项目推出到JDK8
G1(全新的gc收集器)
动态语言增强(动态语言的火热)
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优秀特性
推测:JRockit在不久的将来会退出历史舞台,但是HotSpot会深受JRockit的影响。
JVM种类
KVM
SUN发布
IOS Android前,广泛用于手机系统
CDC/CLDC HotSpot
手机、电子书、PDA等设备上建立统一的Java编程接口
J2ME的重要组成部分
JRockit
IBM J9 VM
IBM内部
Apache Harmony
兼容于JDK 1.5和JDK 1.6的Java程序运行平台
与Oracle关系恶劣 退出JCP ,Java社区的分裂
OpenJDK出现后,受到挑战 2011年 退役
没有大规模商用经历
对Android的发展有积极作用
BEA
Java语言规范
语法定义
IfThenStatement:
if ( Expression ) Statement
if(true){do sth;}
ArgumentList:
Argument
ArgumentList , Argument
add(a,b,c,d);
词法结构
\u + 4个16进制数字 表示UTF-16
行终结符: CR, or LF, or CR LF.
空白符
空格 tab \t 换页 \f 行终结符
注释
标识符
关键字
//标识符:标识符字符串不能使关键字或者布尔值或者null
Identifier: IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral
//标识符串:java字符
IdentifierChars: JavaLetter IdentifierChars JavaLetterOrDigit
//java字符:任何一个unicode
JavaLetter: any Unicode character that is a Java letter (see below)
//
JavaLetterOrDigit: any Unicode character that is a Java letter-or-digit (see below)
小例子
public static void 打印(){
System.out.println("中文方法哦");
}
public static void main(String[] args) {
打印();
}
有意思的是,代码中有中文
数字相关
在jdk1.7中一个比较大的改变是允许有下划线,好处是当数字比较大的时候看的比较清楚一些。
- 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 - 操作
+= -= *= /= &= |= ^= %= <<= >>= >>>=
哪些是合法的数字呢?
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);
}
}
i13 but i24
v1.val6 and v2.val6
i1 i2为不同的变量
v1 v2为引用同一个实例
略
Java内存模型
类加载链接的过程
public static final abstract的定义
异常
数组的使用
…….
JVM规范
Java语言规范定义了什么是Java语言
Java语言和JVM相对独立
符合JVM规范的就能够在JVM上运行,比如:
Groovy
Clojure
Scala
JVM主要定义二进制class文件和JVM指令集等Class 文件格式
数字的内部表示和存储
Byte -128 to 127 (-27 to 27 - 1)returnAddress 数据类型定义
指向操作码的指针。不对应Java数据类型,不能在运行时修改。Finally实现需要定义PC
堆
栈
方法区
整数的表达
- 原码:第一位为符号位(0为正数,1为负数)
- 反码:符号位不动,原码取反
- 负数补码:符号位不动,反码加1
- 正数补码:和原码相同
- 打印整数的二进制表示
int a=-6;
//因为整数有32位,所以进行32次循环。
for(int i=0;i<32;i++){
//0x80000000表示最高位为1的数字,所以a & 0x80000000只有一位是1,
//第一次i=0,就是把a的第一位取出来,无符号右移(31-i)位。
//依次循环,将每一位打印出来
int t=(a & 0x80000000>>>i)>>>(31-i);
System.out.print(t);
}
5
00000101
-6
原码: 10000110
反码: 11111001
补码: 11111010
-1
原码: 10000001
反码: 11111110
补码: 11111111
为什么要用补码?
0是一个比较特殊的数字,既不属于正数,也不属于负数
计算0的表示:
0
正数:00000000
负数:10000000
0
正数:00000000
0
负数:10000000
反码:11111111
补码:00000000
看到这里补码的好处是为了没有歧义的表示零
-6+5
11111010
+ 00000101
= 11111111
-4+5
11111100
+ 00000101
= 00000001
-3+5
11111101
+ 00000101
= 00000010
看到这里,补码还有一个好处就是方便的计算两个数字之和(两个补码之和,符号位直接参与运算,得到的记过就是正确的结果。如果是源码做计算,符号位参与运算得不到正确的结果。),当然减法是一个特殊的加法。
Float的表示与定义
支持 IEEE 754
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
s符号位 eeeeeeee 指数:8 mmmmmmmmmmmmmmmmmmmmmmm 尾数:23
e全0 尾数附加位为0 否则尾数附加位为1,所以这里的尾数看似是23位,实质上是24位。
表达式
s*m*2^(e-127)
m指的是后面的23位
例子
-5
1 10000001 01000000000000000000000
-1*2^(129-127)*(2^0+2^-2)
一些特殊的方法
clinit 类的初始化方法
init 实例的初始化方法
JVM指令集
- 类型转化
l2i - 出栈入栈操作
因为虚拟机没有寄存器,所以很多的指令都是通过栈的方式来操作的,所以有一系列的指令来定义出栈和入栈的操作。
aload astore - 运算
iadd(+) isub(-) - 流程控制
ifeq(相等) ifne(不相等) - 函数调用
invokevirtual(调用虚函数) invokeinterface (调用接口) invokespecial invokestatic (调用静态)
JVM需要对Java Library 提供以下支持:
因为这些功能没有办法通过java语言本身支持,所以通过JVM实现。
- 反射 java.lang.reflect
- ClassLoader
- 初始化class和interface
- 安全相关 java.security
- 多线程
- 弱引用
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指令代码(如上)。
JVM内核-原理、诊断与优化学习笔记(一):初识JVM的更多相关文章
- 深入JVM内核---原理,诊断与优化
JVM的概念 JAM是Java Virtual Machine的简称.意为Java虚拟机 虚拟机 指通过软件模拟的具有完整硬件系统功能的,运行在一种完整隔离环境中的完整计算机系统 有哪些虚拟机 - V ...
- JVM内核-原理、诊断与优化学习笔记(八):JAVA堆分析
文章目录 内存溢出(OOM)的原因 在JVM中,有哪些内存区间? 堆溢出 永久区 Java栈溢出 直接内存溢出 小问题? MAT使用基础 柱状图显示 支配树 显示线程信息 显示堆总体信息,比如消耗最大 ...
- JVM内核-原理、诊断与优化学习笔记(七):性能监控工具
文章目录 系统性能监控 系统性能监控- linux uptime top vmstat(虚拟内存统计) pidstat 系统性能监控 - windows 任务管理器 Perfmon Process E ...
- JVM内核-原理、诊断与优化学习笔记(四):GC算法与种类
文章目录 GC的概念 GC算法 引用计数法 引用计数法的问题 标记清除 标记压缩 小问题 复制算法 复制算法的最大问题是:空间浪费 整合标记清理思想 -XX:+PrintGCDetails的输出 gc ...
- JVM内核-原理、诊断与优化学习笔记(三):常用JVM配置参数
文章目录 Trace跟踪参数 -verbose:gc (打开gc的跟踪情况) -XX:+printGC(打开gc的log开关,如果在运行的过程中出现了gc,就会打印出相关的信息.) -XX:+Prin ...
- JVM内核-原理、诊断与优化学习笔记(二):JVM运行机制
文章目录 JVM启动流程 PC寄存器 方法区 保存装载的类信息 通常和永久区(Perm)关联在一起 Java堆 Java栈 Java栈 – 局部变量表 ** 包含参数和局部变量 ** Java栈 – ...
- JVM内核-原理、诊断与优化学习笔记(六):类装载器
文章目录 class装载验证流程 class装载验证流程 class装载验证流程 -加载 class装载验证流程 -链接 验证 链接 -> 验证 文件格式的验证 元数据验证(class文件简单语 ...
- JVM内核-原理、诊断与优化学习笔记(十一):JVM字节码执行
文章目录 javap javap 举个
- JVM内核-原理、诊断与优化学习笔记(十):Class文件结构
文章目录 语言无关性 文件结构 魔数 版本 常量池 CONSTANT_Utf8 CONSTANT_Integer CONSTANT_String CONSTANT_NameAndType CONSTA ...
随机推荐
- 「题解」:$Six$
问题 A: Six 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...
- WebBug靶场基础篇 — 02
本篇以第一人称记录这个关卡的第 1-5 关. 由于我记录的过程有点偏向于思考,所以截图截的多 = =!所以文章有点长... 下午一觉醒来,已经 4 点多了,然后开电脑,在虚拟机里,铺了铺靶场,但是毕竟 ...
- 项目管理模式:外瀑布内敏捷(有人称为“信封法”)--转自知乎大神:CORNERSTONE
作者:CORNERSTONE 链接:https://www.zhihu.com/question/265968122/answer/878124580 来源:知乎 著作权归作者所有.商业转载请联系作者 ...
- source insight和vim同时使用
https://blog.csdn.net/wangn222/article/details/72721993 1.Source Insight中,Options->Custom Command ...
- 引入scss(@import)和其中易错点
1.引入文件方式 @import 'url'; ./ :当前目录 ../ :上级目录 src/api/styles: 绝对路径 2.一般在main.js中引用当做全局样式 import 'styles ...
- 拾遗:使用 systemd-journald 管理 Docker 容器日志
在 docker.service 文件中的 ExecStart 字段中,添加(或:docker run --log-driver=journald): --log-driver=journald \ ...
- LitJson使用中的一些问题
http://blog.csdn.net/n5/article/details/45030063
- jsonp的实现原理
jsonp的实现原理 由于浏览器的安全性(同源策略)限制,不允许AJAX访问协议不同或域名不同或端口号不同的数据接口: 可以通过动态创建script标签的方式,把script标签的src属性指向数据接 ...
- 基于nginx结合openssl实现https
[root@localhost ~]#systemctl stop firewalld[root@localhost ~]#setenforce 0[root@localhost ~]#iptable ...
- hdu5421 Victor and String 回文树(前后插入)
题目传送门 题意:对一个字符串支持四种操作,前插入字符,后插入字符,询问本质不同的回文串数量和所有回文串的数量. 思路: 就是在普通回文树的基础上,维护suf(最长回文后缀)的同时再维护一个pre(最 ...