.java文件---(编译)-->.class文件(字节码文件)--->(jvm解释)---->二进制机器码
jvm类加载过程为:
1,装载,查找和导入Class文件.
2,链接:
1,验证,确保Class文件中的二进制信息符合当前虚拟机的要求。
2,准备:为类变量分配内存并设置类变量初始值( 这时候分配内存和初始化的仅是static变量,实例变量需要在类加载时分配在java堆中)。
3,解析:将常量池中的符号引用替换成直接引用。(简单来说,符号引用就是字符串,包含类的相关信息,凭借此可以找到相应的位置,直接引用就是偏移量,通过直接引用可以直接在内存区域中找到字节码起始位置)
3,类初始化
准备阶段和初始化阶段并不矛盾,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存,然后进行链接的验证,验证通过后在方法区内给a分配内存,并初始化为0,然后解析,在初始化时,才把10赋给a,此时a=10。
类的加载的双亲委派模型:
类的加载指的是将类的class文件中的二进制数据读入到内存中,将其放在方法区内,然后在java堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象.
流程:
1, 产生一个Bootstrap Loader类.
2,Bootstrap自动加载Extended Loader,并将其父Loader设为Bootstrap Loader。
3,Bootstrap自动加载AppClass Loader(系统加载器),并且将其父Loader设为Extended Loader.
4,由AppClass Loader加载该类.
双亲委培模型:就是类接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
双亲委派模型的意义:
使得类加载器具有层次结构,所有相同的类在各种类加载器环境中都是同一份字节码.
public class HelloWorld {
public static void main(String[] args) {
HelloWorld hello=new HelloWorld();
Class c=hello.getClass();
System.out.println(c);//HelloWorld类
ClassLoader loader=c.getClassLoader();
System.out.println(loader);//AppLoader类
System.out.println(loader.getParent());//Extended Loader类
System.out.println(loader.getParent().getParent());//BootStrap类(因为是用c写的,所以找不到返回方式)
}
}
自定义类加载器没有指定父类加载器的情况下,默认的父类加载器即为系统类加载器(实现类为AppClass Loader)
能不能自己写个类叫java.lang.System?
不行。爸爸们能找到的类,儿子就没有机会加载,而System类是Bootstrap加载器加载的,就算自己重写,也总是使用系统提供的System,自己写的System类根本没有机会得到加载。http://blog.csdn.net/tang9140/article/details/42738433
class SingleTon {
private static SingleTon singleTon = new SingleTon();
public static int count1;
public static int count2 = 0;
private SingleTon() {
count1++;
count2++;
}
public static SingleTon getInstance() {
return singleTon;
}
}
public class Test2 {
public static void main(String[] args) {
SingleTon singleTon = SingleTon.getInstance();
System.out.println("count1=" + singleTon.count1);
System.out.println("count2=" + singleTon.count2);
}
}
错误答案
count1=1
count2=1
正确答案
count1=1
count2=0
分析:
2:类加载的时候在准备过程中为类变量分配内存并初始化默认值 singleton=null ,count1=0,count2=0
3:类初始化化,为类的静态变量赋值和执行静态代码快。按照顺序 singleton赋值为new SingleTon()调用类的构造方法
4:调用类的构造方法后count=1;count2=1
5:继续为count1与count2赋值,此时count1没有赋值操作,所有count1为1,但是count2执行赋值操作就变为0
class SingleTon {
public static int count1;
public static int count2 = 0;
private static SingleTon singleTon = new SingleTon();
private SingleTon() {
count1++;
count2++;
}
public static SingleTon getInstance() {
return singleTon;
}
}
public class Test2 {
public static void main(String[] args) {
SingleTon singleTon = SingleTon.getInstance();
System.out.println("count1=" + singleTon.count1);
System.out.println("count2=" + singleTon.count2);
}
}
count1=1