我们学习Java,总是学习Java的语法,而对于虚拟机或者说HotSpot虚拟机却关注的不是太多,想了解虚拟机这部分内容,去问老师,最终的不到想要的答案。所以只能一本书看N遍,才有一点小小的理解,由于我知识浅薄,有些东西不是很完善,希望大佬们不要介意,有什么问题希望大家提出来一起讨论。
类加载的几个阶段:加载,验证,准备,链接,初始化,运用和卸载几个部分。
需要类加载的几个情况:
1.遇到一些特殊的字符和元语new,getstatic,putstatic或invokestatic等指令,如果没有进行初始化,对其进行初始化;
2.使用反射进行初始化,java.lang,reflect类进行调用(这个反射可以进行私有构造器的调用)
3.当初始化一个类的时候,发现父类没有初始化,先给父类进行初始化
4.当虚拟机启动类,用户需要制定一个main方法(所有的Java类加载时候都需要main方法,包括Tomcat启动仍然使用main方法)
5.使用一些方法句柄
几种情况不会导致初始化的:
1.子类调用父类的静态字段;
2.数组定义的引用类;
3.常量放入产量池。
类加载的几个阶段:
1.加载阶段:
1).通过一个类的全限定类名来获取二进制流(详细实践请参照ClassLoader类中的findClass);
2).将这个字节流所代表的静态存储结构转化为运行时数据结构;
3).在内存中生成一个Java.lang.Class,表示访问的入口;
(加载阶段可以用引导类加载器或者自定义加载器,加载器是满足双亲委托模型,本类加载器缓存没有找到,就访问父类,最后到引导加载器,如果没有进行类加载)
(注意:数组不是通过这种形式来进行创建的,数组只有虚拟机直接创建的,数组中的元素则通过这种形式创建)
外部的二进制流进入方法区以后,class对象作为访问方法区的类接口的入口;
2.验证阶段:
验证阶段主要对.class的文件合法性进行验证,从而来保护虚拟机。
1).文件类型验证,就是验证魔数是否是.class的魔数;
2).元数据校验主要对Java语法的合法性进行一个验证,判断Java语法是否合法;
3).字节码校验:保证字节码不能危害到虚拟机安全;
4).符号引用认证:符号引用地址是否符合要求;
3.准备:
正式为类变量分配内存,设置初始值;
如果修饰符为static这一类的修饰的类变量,则初始化设置为0,如果final则直接写入设置的值。
4.解析:
解析阶段是虚拟机将常量池内的符号引用替换直接引用(在虚拟机的几个内存区域中,Java对象存储在栈区,使用指针引用去直接查找)。
1)类或接口解析;
2)字段解析;
3)类方法解析;
4)接口方法解析;
5.使用<clinit>元语进行初始化,执行完成后生成字节码。
类加载阶段结束。
几点注意:
1.<clinit>自动收集所有变量的赋值动作和静态语句块中的语句合并产生的,顺序由源文件出现的顺序;
2.子类类加载前,父类先类加载;
3.父静态语句优于子静态语句执行;
执行完类加载以后,才可进行实列加载阶段(new):
1.<init> 进行创建通知;
2.实例变量初始化
3.构造方法;