java类加载过程
2017-04-08 12:49
260 查看
.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加载该类.
双亲委培模型:就是类接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
双亲委派模型的意义:
使得类加载器具有层次结构,所有相同的类在各种类加载器环境中都是同一份字节码.
自定义类加载器没有指定父类加载器的情况下,默认的父类加载器即为系统类加载器(实现类为AppClass Loader)
能不能自己写个类叫java.lang.System?
不行。爸爸们能找到的类,儿子就没有机会加载,而System类是Bootstrap加载器加载的,就算自己重写,也总是使用系统提供的System,自己写的System类根本没有机会得到加载。http://blog.csdn.net/tang9140/article/details/42738433
错误答案
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
如果我们修改代码:
count1=1
count2=1
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
相关文章推荐
- JAVA类的生命周期和虚拟机加载过程
- 从一道面试题来认识java类加载时机与过程【转】
- java类的加载过程
- 从一道面试题来认识java类加载时机与过程
- java类加载机制的过程
- 对Java类加载、实例化执行过程的理解
- 从一道面试题来认识java类加载时机与过程
- java类加载过程
- 【转】 Java类加载全过程
- 详细解说Java类加载全过程
- Java类加载与实例化过程
- java类加载过程
- 从一道面试题来认识java类加载时机与过程
- java类的加载过程
- Java类加载基本过程
- java类加载全过程
- 从一道面试题来认识java类加载时机与过程
- 从一道面试题来认识java类加载时机与过程 - 天魂地煞
- Java类加载过程
- JAVA类的加载和对象初始化过程