为什么要使用类加载器?
java语言里,类加载都是在程序运行期间完成的,这种策略虽然会令类加载时稍微增加一些性能开销,但是会给java应用程序提供高度的灵活性。例如:
1.编写一个面向接口的应用程序,可能等到运行时再指定其实现的子类;
2.用户可以自定义一个类加载器,让程序在运行时从网络或其他地方加载一个二进制流作为程序代码的一部分;(这个是android插件化,动态安装更新apk的基础)
为什么研究类加载全过程?
类加载机制
jvm把class文件加载到内存,并对数据进行校验、解析和初始化,最终形成jvm可以直接使用的java类型的全过程。
加载
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.class
对象,作为方法区类数据的访问入口,这个过程需要类加载器参与。
链接
将java类的二进制代码合并到jvm的运行状态之中的过程
初始化
<clinit>()
方法的过程。类构造器<clinit>()
方法是由编译器自动收藏类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生<clinit>()
方法在多线程环境中被正确加锁和同步例1:
public class demo01 { public static void main(string[] args) { a a = new a(); system.out.println(a.width); } } class a{ public static int width=100; //静态变量,静态域 field static{ system.out.println("静态初始化类a"); width = 300 ; } public a() { system.out.println("创建a类的对象"); } }
分析:
说明:
内存中存在栈、堆(放创建好的对象)、方法区(实际也是一种特殊堆)
1、jvm加载demo01时候,首先在方法区中形成demo01类对应静态数据(类变量、类方法、代码…),同时在堆里面也会形成java.lang.class
对象(反射对象),代表demo01类,通过对象可以访问到类二进制结构。然后加载变量a类信息,同时也会在堆里面形成a对象,代表a类。
2、main方法执行时会在栈里面形成main方法栈帧,一个方法对应一个栈帧。如果main方法调用了别的方法,会在栈里面挨个往里压,main方法里面有个局部变量a类型的a,一开始a值为null,通过new调用类a的构造器,栈里面生成a()方法同时堆里面生成a对象,然后把a对象地址付给栈中的a,此时a拥有a对象地址。
3、当调用a.width时,调用方法区数据。
当类被引用的加载,类只会加载一次
类的主动引用(一定会发生类的初始化)
java.lang.reflect
包的方法对类进行反射调用类的被动引用(不会发生类的初始化)
例2:
public class demo01 { static{ system.out.println("静态初始化demo01"); } public static void main(string[] args) throws exception { system.out.println("demo01的main方法!"); system.out.println(system.getproperty("java.class.path")); //主动引用 // new a(); // system.out.println(a.width); // class.forname("com.sinosoft.test.a"); //被动引用 // system.out.println(a.max); // a[] as = new a[10]; system.out.println(b.width);//b类不会被加载 } } class b extends a { static { system.out.println("静态初始化b"); } } class a extends a_father { public static int width=100; //静态变量,静态域 field public static final int max=100; static { system.out.println("静态初始化类a"); width=300; } public a(){ system.out.println("创建a类的对象"); } } class a_father extends object { static { system.out.println("静态初始化a_father"); } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。
如对本文有疑问, 点击进行留言回复!!
[杭电多校2020]第一场 1004 Distinct Sub-palindromes
Swift -- 将本地生成的UIImage进行持久化保存(存到文件中fileManager.createFile)
网友评论