一、类加载机制

  1.类加载机制:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Class文件加载到内存,这就是类加载机制。

  2.类型的加载、连接和初始化过程发生在运行期。

  3.Java动态扩展:依赖运行期动态加载与动态连接。

  4.本地程序运行时Class文件可以来源于网络或者其他地方,称为程序的一部分,如OSGi技术。.

二、类加载时机

  1.类的生命周期  

  • 加载、验证、准备、初始化和卸载:这5个阶段按照如此顺序开始
  • 解析可能发生在使用阶段,来支持运行时绑定

  

  2.初始化发生的5个条件(加载、验证、准备当然要提前完成)

  • 遇到 new、 getstatic、 putstatic 或 invokestatic 这 4 条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。
  • 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  • 当虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类。
  • 当使用 JDK1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果 REF_getStatic、 REF_putStatic、 REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

  3.上述5个条件为对类的主动引用,其他引用类的方式不会触发初始化,称为被动引用

  • 通过子类引用父类的静态字段
  • 通过数组定义引用类,如Shape[] s = new Shape[10];
  • 引用类的static final域,由于在编译阶段会存入调用类(使用者)的常量池,本质并没有直接引用到定义常量的类

三、类加载过程

  1.加载

  1)加载阶段需要完成的三件事

  • 通过一个类的全限定名来获取定义此类的二进制字节流。
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(包括类型信息吧...)。
  • 在内存中生成一个代表这个类的 java. lang. Class 对象,作为方法区这个类的各种数据的访问入口。

  2)数组:不通过类加载器加载,由Java虚拟机直接创建的

  2.验证

  1)目的:自我保护

  2)验证阶段工作量占类加载相当大一部分

  3)具体检验动作

  • 文件格式验证:魔数、版本号、常量池tag、编码等,本种验证基于二进制字节流,通过后,字节流进入内存的方法区储存,后面验证基于内存
  • 元数据验证:语义分析,保证描述信息符合语言规范,如是否有父类、类的父类是否继承了不允许继承的类、如果为抽象类是否实现了所有抽象方法等
  • 字节码验证:确定程序语义合法,如确定数据和指令可以配合工作、保证跳转指令不会跳转到方法体外的字节码指令上、保证类型转换有效(不出现将一个类型转换为另外一个无关类型)等,由于数据流验证的高复杂性,可通过StackMapTable优化
  • 符号引用验证:符号引用转换为直接引用时(解析阶段),如符号引用通过字符串全限定名能否找到对应的类、是否存在所描述的方法和类、符号引用中的类、方法、字段的访问性是否可被当前类访问,其实并非必要!

  3.准备

  • 目的:正式为类变量分配内存并设置类变量的初始值,对于非final变量为0,对于final变量,需要执行其初始化流程

  4.解析

  • 将常量池的符号引用替换为直接引用
  • 符号引用:与内存无关,直接引用:与内存有关
  • 除了invokedynamic指令,JVM可能对第一次解析的结果进行缓存
  • 类或接口解析、字段解析、类方法解析、接口方法解析

  5.初始化

  • 初始化阶段是执行<clinit>()的过程
  • <clinit>():编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并生成
  • 虚拟机保证子类的<clinit>()方法执行之前,父类的<clinit>()方法已经执行完毕
  • 保证执行<clinit>()的线程安全性

四、类加载器

  1.类加载器

  • 类加载过程:JVM之外实现根据一个类的全限定名来获取描述的二进制字节流
  • 类层次划分、OSGi、热部署、代码加密均要依赖这个机制
  • 每一个类加载器,有其独立的类命名空间,同一个类由不同类加载器加载,则加载的类不相等,包括Class对象的equals()、iAssignableFrom()、isInstance()、instanceof

  2.双亲委派

  1)三种类加载器:父子关系通过组合实现非继承

  • 启动类加载器(Bootstrap ClassLoader):这个类将器负责将存放在JAVA_HOME\lib 目录中的,或者被-Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar, 名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用 null 代替即可。
  • 扩展类加载器(Extension ClassLoader):它负责加载JAVA_ HOME\lib\ext 目录中的,或者被 java.ext.dirs 系统变量所指定的路径中的所有类库。
  • 应用程序类加载器(Application ClassLoader):由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径( ClassPath) 上所指定的类库。如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

  2)工作过程  

  

  3.破坏双亲委派(OSGi)

参考:

  https://gavinzhang1.gitbooks.io/java-jvm-us/content/xu_ni_ji_lei_jia_zai_ji_zhi.html

深入理解Java虚拟机5-chap7-斗者2星的更多相关文章

  1. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  2. 《深入理解 java虚拟机》学习笔记

    java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.

  3. (1) 深入理解Java虚拟机到底是什么?

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机   作为一个Java程序员,我们每天都在写Java ...

  4. 深入理解java虚拟机(7)---线程安全 & 锁优化

    关于线程安全的话题,足可以使用一本书来讲解这些东西.<Java Concurrency in Practice> 就是讲解这些的,在这里 主要还是分析JVM中关于线程安全这块的内容. 1. ...

  5. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  6. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  7. 深入理解java虚拟机(4)---类加载机制

    类加载的过程包括: 加载class到内存,数据校验,转换和解析,初始化,使用using和卸载unloading过程. 除了解析阶段,其他过程的顺序是固定的.解析可以放在初始化之后,目的就是为了支持动态 ...

  8. 深入理解java虚拟机(1)------内存区域与内存溢出

    在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻. 而Java确把这一工作交给了虚拟机来处理. 我们首先来看看关于内存的问题. 1.问题: 1)java ...

  9. 什么是HotSpot VM & 深入理解Java虚拟机

    参考 http://book.2cto.com/201306/25434.html 另外,这篇文章也是从一个系列中得出的: <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> ...

  10. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

随机推荐

  1. x-www-form-urlencoded与multipart/form-data区别

    转载声明: http://blog.chinaunix.net/uid-7210505-id-329700.html 在Flex中,UrlRequest中的contentType默认值为 applic ...

  2. HTTP 05 安全

    TCP 打包时加密, 报文传输时 加密 通过证书来判断是否是可以访问的客户端/服务器. 公开秘钥 进行加密, 随便被人知道 私有秘钥 进行解密, 自己保留 http + 加密 + 认证 + 完整性保护 ...

  3. MySQL 批量写入数据报错:mysql_query:Lost connection to MySQL server during query

    场景: 批量往mysql replace写入数据时,报错. 解决方法: 1.增大mysql 数据库配置中 max_allowed_packet 的值 max_allowed_packet = 1G ( ...

  4. 给你的app添加桌面widget

    首先,什么是桌面widget,桌面widget是一种桌面插件,如下图: 这种类型的控件叫做widget,一般长按桌面会弹出一个界面让你选择控件,选择完了拖到桌面就能使用了. 下面我们为这个app来添加 ...

  5. 乾坤合一~Linux设备驱动之USB主机和设备驱动

    如果不能陪你到最后 是否后悔当初我们牵手 如果当初没能遇见你 现在的我 在哪里逗留 所有的爱都是冒险 那就心甘情愿 等待我们一生中 所有悬念 我一往情深的恋人 她是我的爱人 她给我的爱就像是 带着露水 ...

  6. Ubuntu下pdf和图片互转

    前边文章可以将ppt转换为pdf  查看 使用unoconv将ppt转为pdf,再使用imagemagick将pdf转为图片 这次想将pdf和图片进行互转 当前目录下只有2.ppt 1.ppt转pdf ...

  7. fiddler 使用记录

    fiddler 工作原理 Fiddler 启动后将自己变成一个代理服务器,这个代理服务器默认监听 127.0.0.1:8888. Filddler 启动后浏览器的代理会被自动更改为 127.0.0.1 ...

  8. [转]Visual Studio 2015源文件编码问题(936)

    在Visual Studio中,如果源文件中包含中文,那么当源文件编码为utf8时,会报“C4819 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据 ...

  9. Android的Base64的坑

    Base64.encodeToString加密后一直和Apache的对不上,多了换行符,最后使用了NO_WRAP就好了 Base64.encodeToString(src, Base64.URL_SA ...

  10. 【Static Program Analysis - Chapter 2】 代码的表征之控制流图

      (a) an if-then-else (b) a while loop (c) a natural loop with two exits, e.g. while with an if...br ...