jvm_6_Class文件校验器

1 功能:

a) 校验确认class文件内容有正确的结构

b) 在字节码执行之前对文件进行校验

2 具体执行过程:

a) 装载字节序列时,针对二进制数据进行校验,校验目的是确认class文件结构的合法性,如果校验失败会抛出异常

eg: 使用windowns下的copy命令去合并一个.class文件和一个jpg文件的时候,装载这个class文件的时候jvm会发现这个class文件被删改过,文件的长度也不正确,而抛出异常!

 

b) 扫描方法区目的是确认类能顺利编译,扫描范围为:方法区,针对语义,词法,语法进行分析

c)  字节码校验: 验证词法

c.1) 字节码流 

     字节码流 =  操作码+操作数

 

 

d)  符号应用校验: 即确认被引用的类,字段,方法确实存在

详细解释:

大部分JVM的实现都是使用延迟加载/动态链接,即:JVM加载类A,而A又引用B,

JVM不会加载B,而是将B相对于A的引用形式登记在符号表中,在真正使用到B时,才会将被引用类B在引用类A的符号引用名改为内存里的直接引用。

因为这个过程发生在方法区中,并且发生时间不可预测,因此这个过程也叫做动态连接。

 

总结下为:

1.查找被引用的类(有必要的话就加载它)

2.将符号引用替换为直接引用,例如一个指向类、字段或方法的指针,下次再需要用到被引用类的时候直接运用直接引用,不需要再去装载。

 

分析ClassLoader类中的loadClass方法,能找到动态连接的踪迹:

 

 protected synchronized Class<?> loadClass(String name, boolean resolve)  
02.throws ClassNotFoundException  
03.   {  
04.// First, check if the class has already been loaded  
05.Class c = findLoadedClass(name);  
06.if (c == null) {  
07.    try {  
08.    if (parent != null) {  
09.        c = parent.loadClass(name, false);  
10.    } else {  
11.        c = findBootstrapClass0(name);  
12.    }  
13.    } catch (ClassNotFoundException e) {  
14.        // If still not found, then invoke findClass in order  
15.        // to find the class.  
16.        c = findClass(name);  
17.    }  
18.}  
19.if (resolve) {  
20.    resolveClass(c);  
21.}  
22.return c;  
23.   }  

 loadClass有两个参数,第一个参数是类的全限定名,第二个参数就是我们要说的重点,这个参数为true的时候表示,loadClass方法会执行resolveClass的方法,这个方法就是将类中的符号引用替换为直接引用。最终调用的方法是一个本地方法 resolveClass0。

Class.forName这个静态的方法我们也常用来加载class文件的字节码,和classLoader.loadClass(String name, boolean resolve) 有什么区别
区别就在于是否执行resolveClass这个方法
Class.forName总是承诺将符号连接进行连接和初始化
loadClass没有这样的承诺, 需要参数来具体指定是否加载

 

 3  class文件校验器脑图:

 

 

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2150917
今日推荐