JVM学习笔记
上周观看了圣思园张龙老师所讲的<深入了解JVM>课程,结合自己的理解对有关类加载器的内容(ClassLoader)做下总结.
一: 什么是类加载器(ClassLoader)?
java跨平台? -- Java源文件编译成了的.class文件(字节码文件)可以在JVM上运行,而JVM可以看成一个独立于各操作系统的平台,JVM会加载编译后的.class文件到内存,由JVM解析执行.
类加载器,就是可以将编译后的.class文件加载到内存,由JVM进而编译执行的类.
二: 类加载器的作用?
1.将.class文件加载到JVM内存中.
三: 类加载器的类别:
1.根类加载器:
①:它没有父类加载器
②:它是由C和C++语言编写的, class.getClassLoader() == null
③:它从系统属性sun.boot.class.path所指定的目录中加载类库,不会继承ClassLoader这个类
2.扩展类加载器
①:它的父类加载器是: 根类加载器
②:它是由Java语言实现的
③: 它从java.ext.dirs系统属性所指定的目录或者${JAVA_HOME}/jre/lib/ext/目录下加载类库,如果用户创建的jar文件放到这个目录下,也会由扩展类加载器进行加载
3.系统类加载器
①:它的父类加载器是: 扩展类加载器
②:它是由Java语言实现的
③:它从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,它是用户自定义类加载器的默认父类加载器.
4.用户自定义类加载器.
①:它的默认父类加载器是:系统类加载器,当然我们也可以在创建的时候指定父类加载器
②:由Java语言实现的,要创建一个用户自定义类加载器,只需要extends ClassLoader这个类,并且Override掉它的findClass()方法就可以了
③:我们在创建自定义类加载器的器的时候可以指定从那些目录进行加载.class文件.
④:一个自定义类加载器的例子(略)
❤Java初高级学习分享,共同学习才是最明智的选择,喜欢的话可以我的学习群64弍46衣3凌9,或加资料群69似64陆0吧3(进群备注平台名)
5:父类加载器的含义:
所谓的父类加载器,并不和Java语言中的extends的含义一样,父子类加载器之间一种组合关系,如果理解成extends的话,那岂不是所有的用户自定义类加载器都是ClassLoader了吗?但这是不正确的.
6:类加载器的父委托机制:(定义类加载器, 初始类加载器)
JDK1.2版本开始,类加载机制采用了父委托机制,在此委托机制中,除了JVM自带的根类加载器以外,其它的类加载器都有且只有一个父类加载器.
例如:假设有两个个自定义类加载器Loader1,Loader2, Loader1的父类加载器是系统类加载器,Loader2的父类加载器是Loader.当Loader2要去加载一个类时,它会首先委托给Loader1去加载,因为Loader1还有父类加载器扩展类加载器,这时它会向上委托给扩展类加载器;同理,扩展类加载器会继续会上委托,直至根类加载器.当根类加载器加载不了这个类时,它会交由它的子类加载器进行加载....直至Loader2这个类加载器.如果Loader2这个类加载器还加载不了,就会抛出ClassNotFoundException.
假定:Loader1可以加载到目标.class文件,那么Loader1这个类加载器就被称为这个类的定义类加载器,而Loader和Loader2都被称为初始类加载器
7:JVM对类的使用方式:
主动使用:
①:创建一个类的实例: new Test();
②:访问某个类或者接口的静态方法,或者对该静态变量赋值Test.a或者Test.a=b
③:调用类的静态方法 Test.methodName();
④:反射使用(如:Class.forName(args);
⑤:初始化一个类的子类
⑥:Java虚拟机启动时被标明启动类的类(包含Main方法的类)
被动使用:
除了以上6种主动使用外,都被称为被动使用,被动使用不会导致类的初始化.
8: JVM对类的加载,连接和初始化(静态变量)
①:加载: 查找并加载类的二进制数据.class文件,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构
②:连接:
ⓐ验证:确保被加载的类的正确性,包括类文件的结构检查,语义检查,字节码验证,二进制兼容的验证
ⓑ准备:为类的静态变量体现内存大小,并将其赋予默认值
ⓒ解析:反类中的符号引用转换成直接引用(符号引用 car.run()
③:初始化
静态变量声明处初始化和静态代码块中初始化.
初始化步骤:
先父类初始化,再子类初始化.
当Java虚拟机初始化一个类时,要求它所有的父类都已经初始化了,但这条规则不适合于接口之间或者类和接口之间
ⓐ:在初始化一个类时,并不会初始化它所实现的接口
ⓑ:初始化一个接口时,并不会先初始化它的父接口,
ⓒ:对子类的"主动使用"会导致父类的初始化,但对父类的"主动使用"不会导致子类的初始化.一个很简单的例子Object类
ⓓ:通过子类访问父类中所定义的静态变量和方法不会引起子类的初始化
ⓔ:父接口不会因为子接口或者其实现类的初始化而初始化,只有当程序首次访问定义在父接口的静态变量时,才会导致该接口的初始化.
9:一个用户自定义类加载器的实现(在我的Java程序中)
10:一些练习题.
11:待补充:类的命名空间的相关知识.
❤提问/互动请留言,可直接在最底右下方"写留言即可"
❤Java初高级学习分享,共同学习才是最明智的选择,喜欢的话可以我的学习群64弍46衣3凌9,或加资料群69似64陆0吧3(进群备注平台名)
❤如果觉得写得不错请点击“订阅”,每天更新全新的内容!
❤你们的喜欢和关注就是我最大的动力支撑!!!