1.编译
java源码 通过 javac 编译成class文件
2.加载
将class文件字节码加载到内存中,并把这些静态数据转化成方法区中运行时的数据结构,在堆中生成一个代表这个类的java.lang.class对象,作为方法区类数据访问的入口。这个过程需要类加载器参与。
加载器有:
引导加载器(bootstrap class loader) 采用c编写的
扩展加载器(extensions class loader) 采用java编写的
应用程序加载器(application class loader) 采用java编写的
自定义加载器 采用java编写
从此到下为从父类到子类,当中加载器之间不是包含关系,而是组合关系。
加载机制有:
双亲委托机制 先从父类加载器找(java默认的加载机制)
线程上下文类加载机制 为了抛弃双亲委派加载链模式 。
自己定义加载器的顺序。每个线程都有一个关联的上下类加载器,如果使用new Therad()方式生成新的线程,新线程将继承其父线程的上下文类加载器。如果程序对线程上下文类加载器没有任何改动的话,程序中所有的线程将都使用系统类加载器作为上下文类加载器。
Tomcat服务器的类加载机制 子类先加载 但是限制类写在指定的地方,如果没写到指定的地方不进行加载。
OSGI加载机制 每个模块都有对应的加载器,它负责加载模块自己包含的java包和类。当它需要加载java核心库的时,它会代理父类加载器(通常是启动类加载器)来完成。当它需要加载所导入的java类时,它会代理个导出此java类的模块来完成加载。模块可以显式的声明某些java包和类,但必须由父类加载器来加载。只需要设置系统属性 org.osgi.framework.bootdelegation的值即可。
3.链接
将java中二进制代码合并到JVM运行状态之中的过程。
这个过程中会有以下三个步骤:
验证: 确保加载类信息符合JVM规范,没有安全方面的问题。
准备 : 正式为类变量(static变量)分配内存并设置类变量的初始值阶段,这些内存都将在方法区中进行分配。
解析 : 虚拟机中常量池中符号引用替换为直接引用的过程。
4.初始化
初始化阶段是执行类构造器<clinit>() 方法的过程,构造器<clinit>()方法是所有类变量赋值的和静态语句块合并产生的。
如果初始化一个类时发现其父类还没进行过初始化,需要先触发其父类的初始化。
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁和同步。
当访问静态域时,只有真正声明这个域的类才会被初始化。