欢迎装载请说明出处:http://blog.csdn.net/yfqnihao

前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,class文件校验器。

class文件 校验器,保证class文件内容有正确的内部结构,java虚拟机的class文件检验器在字节码执行之前对文件进行校验,而不是在执行中进行校验
class文件校验器要进行四趟独立的扫描来完成校验工作

class文件校验器分成四趟独立的扫描来完成校验。

第一趟

在装载字节序列的时候进行,这个是校验class文件的结构的合法性,比如你使用windowns下的copy命令去合并一个.class文件和一个jpg文件的时候,在装载这个class文件的时候jvm会发现这个class文件被删改过,文件的长度也不正确,而抛出异常!
所以这次校验是发生在二进制数据上,

第二趟

扫描发生在方法区中,主要对于,语义,词法和语法的分析,也就是检查这个类是否能够顺利的编译!

第三趟

字节码校验
在这一趟的校验中涉及两个比较不好理解的概念,第一个是字节码流,第二个是栈帧.
执行字节码时,一次执行操作码,java虚拟机内构成了执行线程,而每个线程会有自己的java栈就是我们说的栈帧。每一个方法都有一个栈帧。
如果学过汇编的人理解这两个概念会容易一点
字节码流=操作码+操作数,在这里可以看做汇编里的伪指令+操作数,因为这里的操作码实际上就是给jvm识别的“汇编伪指令”,而操作数的概念和汇编里的除了数据类型,并没有多大的差异
重点来看一下栈帧,栈帧其实也很好理解,栈帧里有局部变量栈操作数栈,这两块内存就是放数据的时机不同,操作数栈就是用来存放字节码指令执行的中间结果,结果或操作数,而局部变量区,就是用来存局部变量形参等,这个很好理解
这个字节码的校验过程校验的就是字节码流的合法过程,也就是校验操作数+操作码的合法性。

而java的class文件编码我们之所以称之为字节码,是因为每调条操作指令都只占一个字节,除了两个例外情况,所有的操作码和他们的操作数按字节对齐,这使得字节流在传输的时候跟小,更有优势,这两个例外是这样一些操作码,在操作码和他们的操作数之间会天上一至三个字节,以便操作数都按字节对齐。

下面是一个图,描述了栈帧的结构

第四趟

符号引用的校验
由于大部分jvm的实现都是延迟加载或者说动态链接的,延迟加载的意思就是,jvm装载某个类A时,如果A类里有引用其他的类B,虚拟机并不会把这个被引用B类也同时装载入内存,而是等到执行到的时候才去装载。
而这个被引用的B类在引用它的类A中的表现形式主要被登记在了符号表中,而第四趟的这个过程就是当需要用到被引用类B的时候,将被引用类B在引用类A的符号引用名改为内存里的直接引用
所以第四趟发生的时间是不可预料的,而且发生在方法区中。总个这个过程称之为动态连接
可以简单的划分为两步
1.查找被引用的类(有必要的话就加载它)
2.将符号引用替换为直接引用,例如一个指向类、字段或方法的指针,下次再需要用到被引用类的时候直接运用直接引用,不需要再去装载。

这个过程其实在ClassLoader类中的loadClass中就可以发现它的痕迹。我们先贴出loadClass这个方法实现,然后简要的做一下分析

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

这里还有一点需要注意,Class.forName这个静态的方法我们也常用来加载class文件的字节码,那它和classLoader有什么区别?

区别就在于是否执行resolveClass这个方法,Class.forName总是承诺将符号连接进行连接和初始化,而loadClass没有这样的承诺。

总结:

第一趟扫描,在类被装载时进行,校验class文件的内部结构,保证能够被正常安全的编译
第二趟和第三趟在连接的过程中进行,这两趟基本上是语法校验,词法校验
第四趟是解析符号引用和直接引用时进行的,这次校验确认被引用的类,字段以及方法确实存在

java jvm学习笔记三(class文件检验器)的更多相关文章

  1. java之jvm学习笔记三(Class文件检验器)

    java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...

  2. Java IO学习笔记三

    Java IO学习笔记三 在整个IO包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换类. OutputStreamWriter:是Writer的子类,将输出的 ...

  3. Java IO学习笔记三:MMAP与RandomAccessFile

    作者:Grey 原文地址:Java IO学习笔记三:MMAP与RandomAccessFile 关于RandomAccessFile 相较于前面提到的BufferedReader/Writer和Fil ...

  4. java jvm学习笔记七(jar包的代码认证和签名)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 前言: 如果你循序渐进的看到这里,那么说明你的毅力提高了,jvm的很多东西都是比较抽像的,如果不找相对应的代码来辅助理解 ...

  5. JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  6. java jvm学习笔记十三(jvm基本结构)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完 ...

  7. java jvm学习笔记十一(访问控制器)

     欢迎装载请说明出处: http://blog.csdn.net/yfqnihao/article/details/8271665 这一节,我们要学习的是访问控制器,在阅读本节之前,如果没有前面几节的 ...

  8. java jvm学习笔记二(类装载器的体系结构)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao                 在了解java虚拟机的类装载器之前,有一个概念我们是必须先知道的,就是java的沙箱,什 ...

  9. [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

随机推荐

  1. 【ASP.NET】TreeView控件学习

    相关链接 : http://www.cnblogs.com/yc-755909659/p/3596039.html

  2. 微软职位内部推荐-Sr Development Lead-OSG-IPX

    微软近期Open的职位: Job Summary:Be part of Microsoft's strategy to deliver a great input experience across ...

  3. linux内核分析之进程地址空间管理

    1.struct task_struct 进程内核栈是操作系统为管理每一个进程而分配的一个4k或者8k内存大小的一片内存区域,里面存放了一个进程的所有信息,它能够完整的描述一个正在执行的程序:它打开的 ...

  4. Delaunay三角剖分

    Bowyer-Watson算法:1.假设已经生成了连接若干个顶点的Delaunay三角网格:2.加入一个新的节点,找出所有外接圆包含新加入节点的三角形,并将这些三角形删除形成一个空洞:3.空洞的节点与 ...

  5. apache与nginx日志文件的区别(转载)

    apache与nginx日志文件的区别 转载:http://www.xfcodes.com/apache/log/3270.htm 导读:apache与nginx日志文件的区别,在apache与ngi ...

  6. Java NIO(New I/O)的三个属性position、limit、capacity

    Java NIO(New I/O)的三个属性position.limit.capacity 在缓冲区中,最重要的属性有下面三个,它们一起合作完成对缓冲区内部状态的变化跟踪: capacity posi ...

  7. 基于内嵌Tomcat的应用开发

    为什么使用内嵌Tomcat开发? 开发人员无需搭建Tomcat的环境就可以使用内嵌式Tomcat进行开发,减少搭建J2EE容器环境的时间和开发时容器频繁启动所花时间,提高开发的效率. 怎么搭建内嵌To ...

  8. hdu 4648

    求一个数列中  去掉一些连续的数之后 不改变对m取余后的值 就是求一个最长的连续子序列 对m取余后为0 我的方法可能比较水 #include<iostream> #include<c ...

  9. C语言:将16进制字符串转化为int类型值

    将16进制字符串值转换为 int 整型值 此例中用 "1de" 作为测试字符串,实现代码如下: #include <stdio.h> #include <stdl ...

  10. C++ 嵌套类使用(一)

    一.嵌套类 在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型.之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的 ...