JVM(Java Virtual Machine) 是Jvm虚拟机的一种规范。
C:\Users\pc>java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
当安装了JDK以后,可以看到默认是已安装HotSpot虚拟机的,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,所以Java语言是跨平台语言。
这也就提现出了Java语言的特点: 一处编译,多处执行,跨平台,安全性(1.摒弃指针 2、GC垃圾回收机制:(自动释放回收长时间不使用对象的内存))
结构:JDK & JRE & JVM三者结构图
工具:javac编译、javap反编译
Java源文件 -> Javac编译成class文件 -> JVM虚拟机运行Class文件实则为转成对应操作系统的机器码 -> 各大操作系统
Javac将源文件转成字节码(词法分析,语法分析,语义分析,字节码生成码)
class文件 一个存放二进制文件,存放16进制的字节
将class文件反编译为cpu指令
//原始代码
static int num = 1;
static final int a1 = 2;
int a2 = 2;
//通过 javap -p -v xxx.class 反编译出来的结果
//会在堆内存中开辟一个num=0的空间
static int num;
descriptor: I
//权限
flags: ACC_STATIC
static final int a1;
descriptor: I
flags: ACC_STATIC, ACC_FINAL
//通知虚拟机给静态变量赋值 意味着准备阶段就已经初始化值了
ConstantValue: int 2
//非static变量的实例变量会随着类变量分配到java堆 在初始化阶段由类构造器初始
int a2;
descriptor: I
目的:将class类加载进虚拟机内存空间中
找到class文件所在的全路径,然后装载到内存中。具体实现由类加载器实现ClassLoader
类加载器类型总览
类加载器 | 功能 |
---|---|
Bootstrap ClassLoader 启动类加载器 | 加载$JAVA_HOME中jre/lib/rt.jar里面所有的class或者Xbootclasspath选项指定的jar包 |
ExClassLoader 扩展类加载器 | 加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或者-Djava.ext-dirs指定目录下的包 |
AppClassLoader 系统类加载器 | 加载classpath中指定的jar包及Djava.class.path指定目录下的类和jar包 |
Custom ClassLoader自定义类加载器 | 通过ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如Tomcat,Jboss都会根据规范自行实现ClassLoader |
类加载方式
自定义类加载器 java实现
实现ClassLoader,加载类不能放到类路径下(否则会被AppClassLoader加载)
验证Verify:验证类的正确性
准备Prepare:为类或接口的静态字段赋值默认值
private static int a =10; 此时会先赋值默认值0
解析Resolve:动态将运行常量池中的符号引用转为直接引用(物理内存地址)
为变量附上真正的值,例如给上面的static int a赋值为10
什么情况触发初始化
根据前面的jvm分布结构图,分为了5个区域,栈、堆、程序计数器、方法区、本地方法栈
OutOfMeoryError: Metespace
Metaspace
OutOfMeoryError: Java heap space
,通过-Xms20M -Xmx20M
设置堆内存大小StackOverfolwError
,栈帧深度默认大小1M,可以通过-Xss 128k
修改public static int calc(int num1,num2){
num1 = 2;
int res = num1 + num2;
return res;
}
calc(1,8);
//通过javap反编译内容 查看下calc栈帧
public static int calc(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
//操作数栈2个 局部变量3个 参数值2个
stack=2, locals=3, args_size=2
0: iconst_2 //push一个int值压入操作栈中 2
1: istore_0 //将操作数栈的值出栈赋值给局部变量的第0个 num1=2
2: iload_0 //第0个局部变量的值压入操作数栈 2
3: iload_1 //第1个局部变量的值压入操作数栈 8
4: iadd //执行一个相加的操作 10
5: istore_2 //将操作数栈的值出栈赋值给局部变量的第2个 res = 10
6: iload_2 //第二个局部变量的值压操作数栈 res
7: ireturn //第二个局部变量出操作数栈 返回10 然后通过方法返回地址到main栈帧
java中的一行代码,可能是多个汇编指令
以上就是本章的全部内容了。
上一篇:MongoDB第二话 – MongoDB高可用集群实现
下一篇:JVM第二话 – JVM内存模型以及垃圾回收
人寿几何?逝如朝霜。时无重至,华不再阳