JVM_第一部分了解JVM

1. java程序之所以能够一次编译,到处运行的特性 主要是因为它存在JVM,整个JDK的体系结构:

JVM_第一部分了解JVM_第1张图片

2.源码到类文件的编译过程

HelloWorld.java --> 词法分析器 --> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> HelloWorld.class

3.类文件到虚拟机(类的加载机制)

1.装载

查找和导入class文件

1.通过一个类的全限定名获取定义此类的二进制字节流

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3.在java堆中生成一个代表这个类的java.lang.class对象作为对方法区中这些数据的访问入口

 

2.链接

2.1验证

  保证被加载类的正确性

文件格式验证

元数据验证

字节码验证

引用符号验证

2.2准备

为类的静态变量分配内存,并将其初始化为默认值

2.3解析

把类中的符号引用转换为直接引用

3.初始化

对类的静态变量,静态代码块进行初始化操作

 

 

类加载机制的完整的生命周期

JVM_第一部分了解JVM_第2张图片

类装载器 ClassLoader 

 

在装载 (Load) 阶段,其中第 (1) : 通过类的全限定名获取其定义的二进制字节流,需要借助类装载
器完成,顾名思义,就是用来装载 Class 文件的。
(1) 通过一个类的全限定名获取定义此类的二进制字节流

分类:

JVM_第一部分了解JVM_第3张图片

加载原则

检查某个类是否已经加载:顺序是自底向上,从 Custom ClassLoader BootStrap ClassLoader 逐层检
查,只要某个 Classloader 已加载,就视为已加载此类,保证此类只所有 ClassLoader 加载一次。
加载的顺序:加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
 
双亲委派机制:
定义:如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把
这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就
成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
 

java运行时数据区

JVM_第一部分了解JVM_第4张图片

方法区:

 方法区是各个线程共享的内存区域,在虚拟机启动时创建

用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据

当方法区无法满足内存分配需求时,将抛出outofMemberError异常

虚拟机栈

虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态,虚拟机栈是私有的随着线程的创建而创建

每一个被线程执行的方法,为该栈中的栈贞,即每个方法对应一个栈贞,调用一个方法就会往栈中压入一个栈贞;一个方法执行完后之后该栈贞就会弹出

栈的深度过深就会产生 StackOverflowError

程序计数器

JVM进程中都会有多个线程在执行,而线程中的内容是否能够有执行权,是根据CPU调度来的

程序计数器占用的内存空间很小,由于java虚拟机的多线程是通过线程轮流切换,并分配处理器执行时间的方式来实现的,在任意时刻,一个处理器只会执行一条线程中的指令,因此为了线程切换后能够恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器(线程私有);

如果线程正在执行java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址

如果正在执行的是native方法,则这个计数器为空

本地方法栈

如果当前线程执行的是native方法,则这些方法会在本地房发栈中执行

java堆是虚拟机所管理的内存最大的一块区域,在虚拟机启动时创建,被所有的线程共享

java对象实例以及数组都是在堆上分配

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(jvm)