——万丈高楼平地起
1、类加载、链接、初始化
1.1 类加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象
1.2 类的连接:
验证:验证阶段用于检验被加载的类是否有正确的内部结构,和其他类协调一致
准备:类准备阶段为类的类变量分配内存,并设置默认初始值
解析:将类的二进制数据中的符号引用替换成直接饮用
1.3 初始化:主要对类变量进行初始化
例:
public class Test { static{ a=1; } public static int a=5; public static void main(String[] args) { System.out.println(Test.a); } }
对上例代码解析:首先把Test.java文件编译成Test.class文件(编译用javac命令)。当运行(java命令)时,开始执行上面的步骤(首次使用该类或预加载该类)。
类加载:生成 Test.class文件读入内存,并生成对应的Class对象,Class对象可以通过Class<Test> c= Test.class 方式获取;
类连接:准备阶段为类变量分配内存,并赋初始值。即4字节空间给变量a使用,并且初始值a=0。(关于默认值可以查询api或找度娘;类似javaScript中声明的提前,即总会把public static int a=0 放入最前面,然后执行a=1;a=5;)
初始化:初始化顺序是从上往下的,即先执行a=1;然后执行a=5;所以输出结果Test.a=5
2、 类初始化时机:一个类什么时候会初始化
2.1 创建类实例。比如通过new 创建对象或通过反射创建对象(创建对象不仅类得到实例化,而且对象也会被实例化)。
2.2 调用某个类的静态方法 或 操作静态属性(static修饰的)。比如上例中在main方法中调用Test.a
2.3 使用反射创建某个类的Class帝乡,比如上例中:Class<Test> c= Test.class 或者 Class<Test> c = Class.forName("Test");此时对象并未初始化,只是类初始化。
2.4 某个类被初始化时,它的父类将先被初始化。
2.5 运行main(主类)方法时。
3、类加载来源:通过不同类加载器
3.1 从本地文件系统加载class文件。例如:平时用IDE(如eclipse)工具编写的程序,将自动编译成class文件,当点击运行时,便是加载的class文件。
3.2 从jar包加载class文件。例如:jdbc编程使用的数据库驱动类jar包,或使用spring框架编写程序,需要下载的很多jar包
3.3 通过网络加载class文件。
3.4 把一个java源程序动态编译,并执行加载。
4、JVM初始化一个类的几个步骤
4.1 假如这个类还没有加载和连接,则程序先加载并连接该类
4.2 假如假如该类的直接父类还没有被初始化,则先初始化其直接父类
4.3 假如了,类中有初始化语句,则系统依次执行这些初始化语句
当执行到3.2初始化父类时,重复3.1~3.3步骤,所以JVM最先初始化的总是java.lang.Object类。
5、java的程序结束
5.1 程序运行到最后正常结束
5.2 程序运行到使用System.exit() 或者 Runtime.getRuntime().exit()代码处
5.3 程序执行中遇到未捕获的异常或错误而结束
5.4 程序所在的平台强制结束了JVM进程。比如:打开任务管理器 ctrl+shift+esc(window7下),找到进程强制结束
时间:2016年1月13日09:56:05
备注:内容主要摘自与李刚老师的“疯狂java讲义”