1、jvm如何识别.class文件
MD5 对.class文件的前四个字节进行加密
识别:通过.class文件的前四个字节进行MD5校验
MD5(MD5是一个加密算法:对.class文件的前四个字节:0xCAFEBABE)
2、加载.class文件
加载===》链接(验证、解析、准备)====》初始化
对象初始化:静态块 实例块 构造函数
方法:a. 提供一系列的get、set方法
b.调用合适的构造函数
静态块和实例块 初始化
3.加载(加载是通过类加载器加载)
类加载阶段就是由类加载器负责根据一个类的权限定名来读取此类的二进制字节流到JVM内部,并储存在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例,这个Class对象在日后就会作为方法区中该类的各种数据的访问入口。这个Class对象并没有规定是在java堆内存中,他比较特殊,虽为对象,但是存放在方法区中。
加载class文件,先加载到JVM中
3.1链接(验证、解析、准备)
a.验证:验证类数据信息是否符合JVM规范,是否是一个有效的字节码文件,验证内容覆盖了类数据信息的格式验证、语义分析、操作验证等
b.准备:为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量不再此操作范围内)。被final修饰的静态变量,会直接赋予原值。
c.解析:虚拟机常量池中的符号引用替代为直接引用的过程。(例如String s = “Tulun”,转化为s = 的地址指向“Tulun”的地址)
4、类加载器(3个)
a: APPClassLoader(应用类加载器)(system class loader)===>classpth路径下所有的jar和目录(加载自己写的类)
b:ExtClassLiader(扩展类加载器)(java核心扩展类)====>jre/lib/ext/*jar(JAVA_HOME/jre/lib/ext)
c: Bootstrap ClassLoader(启动类加载器)===》(自身带的类)(String Object… 返回值为null)
5、双亲委派模型(LoadClass)==》委托上一级进行加载,若不能加载,则回退,直到不能继续回退,回退到APPClassLoader
6、自定义类加载器:###
如果用户想加载一个特定目录下的类时,就要用到用户自定义的类加载器。除了启动类加载器之外,所有的类加载器都是ClassLoader的子类。
如果要编写一个自定义类加载器MyClassLoader,那么自然地MyClassLoader就要继承ClassLoader类。三种重写的方法:loadClass方法、findClass方法 、defineclass方法
findClass“调用次数<=loadClass调用次数”
a. loadClass: 负责以双亲委托方法去加载类
b. findClass:就根据类的包路径找到class文件
c. defineClass: 负责从class字节码中加载Class对象,然后Class对象通过反射机制才生成对象的。(new instance)
7、如何实现一个类加载器
原则:a. 不能破坏双亲委派模型
b. 重写一个方法 : findClass方法
8、双亲委派模型的好处:###
a: 安全性
b:避免类的重复加载
c:java类随他的类加载器一起具备了一种带有优先级的层次文件
使用双亲委派模型的好处:
(1)安全性,避免用户自己编写的类动态替换Java的一些核心类。如果不采用双亲委派模型的加载方式进行类的加载工作,那我们就可以随时使用自定义的类来动态替代Java核心API中定义的类。例如:如果黑客将“病毒代码”植入到自定义的String类当中,随后类加载器将自定义的String类加载到JVM上,那么此时就会对JVM产生意想不到“病毒攻击”。而双亲委派的这种加载方式就可以避免这种情况,因为String类已经在启动时就被引导类加载器进行了加载。
(2)避免类的重复加载,因为JVM判定两个类是否是同一个类,不仅仅根据类名是否相同进行判定,还需要判断加载该类的类加载器是否是同一个类加载器,相同的class文件被不同的类加载器加载得到的结果就是两个不同的类。
(3)Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类,可以正常编译,但是永远无法被加载运行
9、例子
下面有关java类加载器,说法正确的是(ABC)
A.引导类加载器(bootstrap class loader):它用来加载Java核心库,是用原生代码来实现的
B.扩展类加载器(extensions class loader):它用来加载Java的扩展库
C.系统类加载器(system class loader):它根据Java应用的类路径(CLASSPATH)来加载Java类
D.tomcat为每个App创建一个Loader,里面保存着此WebApp的ClassLoader。需要加载WebApp下的类时,就取出ClassLoader来使用。