java类加载过程

来源:互联网 发布:图像形状特征提取算法 编辑:程序博客网 时间:2024/05/19 13:21

.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

分析:

1:SingleTon singleTon = SingleTon.getInstance();调用了类的SingleTon调用了类的静态方法,触发类的初始化
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
count2=1




















0 0
原创粉丝点击