1.前言

  java是跨平台语言,主要是因为它的java虚拟机的存在,java有事编译语言,所以需要将编写的java文件编译成jvm可运用的class字节码文件。在java中一切皆对象。对于Java虚拟机而言,一个Java类也是一个对象。一个类在JVM中被实例化成一个对象,需要经历三个过程:加载、链接和初始化。

2.加载

  通过读取字节码二进制.class文件将类加载到内存,从而达到类的从硬盘上到内存上的一个迁移,所有的class必须加载到内存才能工作。一个Java类在被加载到内存后会在Java堆中创建一个类(java.lang.Class)对象,同时JVM为每个类对象都维护一个常量池(类似于符号表)并将这个字节流代表的静态存储结构转换为方法区的运行时数据结构。

  • Bootstrap ClassLoader:这个加载器不是一个Java类,而是由底层的c++实现,负责在虚拟机启动时加载Jdk核心类库以及加载后两个类加载器。
  • Extension ClassLoader:是一个普通的Java类,继承自ClassLoader类,负责加载{JAVA_HOME}/jre/lib/ext/目录下的所有jar包。
  • App ClassLoader:是Extension ClassLoader的子对象,负责加载应用程序classpath目录下的所有jar和class文件。
  • 自定义类加载器

3.链接

  (1)验证

  验证是类加载的第二个阶段,这个阶段也是持续时间最长(从阶段连续性来说),这个阶段从加载开始进行,一直进行到解析阶段结束。验证是为了保证class文件中的内容是符合虚拟机规范的二进制字节流,防止通过执行一些不安全的二进制字节流而导致虚拟机奔溃。 从整体来看,类加载过程的验证阶段可以分为四个部分:文件格式验证、元数据验证、字节码验证和符号引用验证。

  (2)准备

  准备阶段是证实为类变量分配内存并且设置初始化值的阶段,这些变量所使用的内存都在方法区分配。这个阶段进行初始化的数据只有静态字段,并且是赋值初始化值(final修饰的字段除外),不是代码中定义的值。   

  public static int value = 123;在准备阶段,value在方法区分配内存,并且设置初始值0,如果value被final修饰,形如:public static final int value = 123;则该变量在准备阶段将会被赋值123,并且不会引起类的初始化过程,示例及说明见第二部分(类加载的时机)的示例。

  (3)解析

  解析阶段是虚拟机将符号引用转化为直接引用的过程,符号引用在之前已经介绍过了,在class文件中以形如"CONSTANT_Class_info"、"CONSTANT_Fieldref_info"、"CONSTANT_Methodref_info"格式存在。符号引用是指在class文件内部的引用指向,也就是说,在class文件内部,会对各个方法,变量进行编号,当存在方法之间的调用或变量之间的引用时,以此编号为引用,找到调用的方法和变量。直接应用就是在对方法和变量解析之后将方法和变量的地址值返回到调用方,以便在调用的时候快速直接的定位方法和变量。由于在class文件没有加入到jvm时,我们是不知道方法的具体分配位置的,所以以符号引用表示,到class加载之后,在这个运行环境中,我们是可以定位方法和变量的地址的。所以在此时做解析。

4.初始化

  初始化阶段是类加载过程的最后一步,这个阶段才开始真正的执行用户定义的Java程序。在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则需要为类变量(非final修饰的类变量)和其他变量赋值,其实就是执行类的<clinit>()方法。在Java语言体系中,<clinit>()是由编译器生成的,编译器在编译阶段会自动收集类中的所有类变量的赋值动作和静态语句块(static{})中的语句合并而成的,编译器收集的顺序是由语句的顺序决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在静态语句块之后的变量,可以赋值,但是不能访问。

  <clinit>()方法与类的构造方法不同,它不需要用户显示的调用,虚拟机会保证父类的<clinit>()方法先于子类的<clinit>()执行,java.lang.Object的<clinit>()方法是最先执行的。接口中不能使用用静态语句块,所以接口的<clinit>()只包含类变量,所以接口的<clinit>()方法执行时,不要求限制性父接口的<clinit>()方法。<clinit>()方法对于类和接口来说不是必须的,如果类或接口中没有定义类变量,也没有静态语句块,那么编译器将不为这个类或者接口生成<clinit>()方法,如果类或者接口中生成了<clinit>()方法,那么这个方法在执行过程中,虚拟机会保证在多线程环境下的线程安全问题。

  虚拟机规范给了严格规定,有且只有以下几种情况必须立即对类进行初始化:
    1、遇到new、putstatic、getstatic及invokestatic这4条字节码指令时,如果类没有初始化,则立即进行初始化,这4个命令分别代表实例化一个类、设置&读取一个静态字段(没有被final修饰)、调用类的静态方法;
    2、使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有初始化;
    3、当初始化一个类的时候,发现其父类没有初始化;
    4、当虚拟机启动时,需用将执行启动的主类(有main()方法的那个类)进行初始化;
   5、当使用动态语言时,如果一个java.lang.invoke.MethodHandle实例最终的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic句柄时,并且这个句柄对应的类没有初始化。

感谢:https://blog.csdn.net/u010942465/article/details/81709246

java类加载及类初始化的更多相关文章

  1. 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)

    本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...

  2. Java类加载和类反射回顾

    今天学习Spring,突然想重新复习一下Java类加载和类反射的.巩固一下底层原理.部分参考了李刚老师的<疯狂Java讲义>和陈雄华.林开雄的<Spring3.x企业应用开发实战&g ...

  3. java类加载和对象初始化

    对象初始化过程:  1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化:  2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化:  3.其次,初 ...

  4. JAVA基础2——类初始化相关执行顺序

    类初始化相关执行顺序 几个概念说明 代码块的含义与作用 static静态代码块: 一般用于初始化类中的静态变量.比如:给静态的数组或者list变量赋初值.使用static静态代码块进行初始化与直接在定 ...

  5. java中的类加载器ClassLoader和类初始化

    每个类编译后产生一个Class对象,存储在.class文件中,JVM使用类加载器(Class Loader)来加载类的字节码文件(.class),类加载器实质上是一条类加载器链,一般的,我们只会用到一 ...

  6. Java程序设计19——类的加载和反射-Part-A

    1 本文概要 本章介绍Java类的加载.连接和初始化的深入知识,并重点介绍Java反射相关的内容.本章知识偏底层点,这些运行原理有助于我们更好的把我java程序的运行.而且Java类加载器除了根加载器 ...

  7. 一文读懂Java类加载机制

    Java 类加载机制 Java 类加载机制详解. @pdai Java 类加载机制 类的生命周期 类的加载:查找并加载类的二进制数据 连接 验证:确保被加载的类的正确性 准备:为类的静态变量分配内存, ...

  8. ClassLoader类加载器 & Java类加载机制 & 破坏双亲委托机制

    ClassLoader类加载器 Java 中的类加载器大致可以分成两类: 一类是系统提供的: 引导类加载器(Bootstrap classloader):它用来加载 Java 的核心库(如rt.jar ...

  9. jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解

    一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机:  1 ...

随机推荐

  1. 【从零开始自制CPU之学习篇00】开篇

    从今天开始决定用面包板制作一个8位的CPU,实现几个简单的指令.我给自己分两大部分计划,第一部分是学习制作CPU的理论知识,第二部分是实践.并打算实施计划的同时用博客的方式记录下来.理论知识的部分重点 ...

  2. vue踩坑--TypeError: __WEBPACK_IMPORTED_MODULE_1_vuex__.a.store is not a constructor

    今天在使用vuex的时候遇到这么个问题,虽然后来解决了,是首字母大写的原因,但我还是不知道为什么.这里先记录下来. 这是vuex/store.js import Vue from 'vue' impo ...

  3. DDD实战进阶第一波(十五):开发一般业务的大健康行业直销系统(总结篇)

    前面我们花了14篇的文章来给大家介绍经典DDD的概念.架构和实践.这篇文章我们来做一个完整的总结,另外生成一个Api接口文档. 一.DDD解决传统的开发的几大问题: 没有描述需求的设计模型:而是直接通 ...

  4. 设计模式总结篇系列:模板方法模式(Template Method)

    模板方法模式需要开发抽象类和具体子类之间的协作.抽象类负责给出一个算法的轮廓和骨架,子类则负责给出这个算法的各个逻辑步骤.代表这些具体逻辑步骤的方法称做基本方法(primitive method):而 ...

  5. 我们知道CDN护航了双11十年,却不知道背后有那么多故事……

    情不知如何而起,竟一往情深.恰如我们.十年前,因为相信,所以看见.十年后,就在眼前,看见一切. 当2018天猫双11成交额2135亿元的大屏上,打出这么一段字的时候,参与双11护航的阿里云CDN技术掌 ...

  6. 关于HTML相关知识随记

    HTML是构成网页文档的主要语言,它由HTML标签和字符信息组成.HTML标签可以标识文字.图形.动画.声音.表格.超链接等网页对象,字符信息用以传达网页内容,如标题.段落文本.图像等. HTML4文 ...

  7. Redis in python

    什么是Redis 数据库类型分为两种,关系型和非关系型,Redis是一个非常重要的非关系型数据库. 既然是数据库,就是存储数据的一个空间,或者说是一个软件,非关系就是不再按照一对一多对多等结构进行外键 ...

  8. 第1章 背景 - Identity Server 4 中文文档(v1.0.0)

    大多数现代应用程序或多或少看起来像这样: 最常见的互动是: 浏览器与Web应用程序通信 Web应用程序与Web API进行通信(Web应用程序自身 或 代表用户 与 Web API 通信) 基于浏览器 ...

  9. shell32.dll 控制网络

    //禁用 SetNetworkAdapter(False) //启用 SetNetworkAdapter(True) //添加引用system32/shell32.dll private static ...

  10. python多线程爬虫+批量下载斗图啦图片项目(关注、持续更新)

    python多线程爬虫项目() 爬取目标:斗图啦(起始url:http://www.doutula.com/photo/list/?page=1) 爬取内容:斗图啦全网图片 使用工具:requests ...