HelloWorld.java --> 词法分析器 --> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> HelloWorld.class
查找和导入class文件
1.通过一个类的全限定名获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3.在java堆中生成一个代表这个类的java.lang.class对象作为对方法区中这些数据的访问入口
文件格式验证
元数据验证
字节码验证
引用符号验证
为类的静态变量分配内存,并将其初始化为默认值
把类中的符号引用转换为直接引用
对类的静态变量,静态代码块进行初始化操作
类装载器 ClassLoader
分类:
加载原则
方法区:
方法区是各个线程共享的内存区域,在虚拟机启动时创建
用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
当方法区无法满足内存分配需求时,将抛出outofMemberError异常
虚拟机栈
虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态,虚拟机栈是私有的随着线程的创建而创建
每一个被线程执行的方法,为该栈中的栈贞,即每个方法对应一个栈贞,调用一个方法就会往栈中压入一个栈贞;一个方法执行完后之后该栈贞就会弹出
栈的深度过深就会产生 StackOverflowError
程序计数器
JVM进程中都会有多个线程在执行,而线程中的内容是否能够有执行权,是根据CPU调度来的
程序计数器占用的内存空间很小,由于java虚拟机的多线程是通过线程轮流切换,并分配处理器执行时间的方式来实现的,在任意时刻,一个处理器只会执行一条线程中的指令,因此为了线程切换后能够恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器(线程私有);
如果线程正在执行java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址
如果正在执行的是native方法,则这个计数器为空
本地方法栈
如果当前线程执行的是native方法,则这些方法会在本地房发栈中执行
堆
java堆是虚拟机所管理的内存最大的一块区域,在虚拟机启动时创建,被所有的线程共享
java对象实例以及数组都是在堆上分配