第十章 类的生命周期

10.1 Java虚拟机及程序的生命周期

当通过java命令运行一个Java程序时,就启动了一个Java虚拟机进程。Java虚拟机进程从启动到终止的过程,称为Java虚拟机的生命周期。在以下情况下,Java虚拟机会结束生命周期:

程序正常结束

程序在执行中因为出现异常或错误而异常终止

执行了System.exit()方法

由于操作系统出现错误而导致Java虚拟机进程终止

当Java虚拟机处于生命周期时,它的总任务就是运行Java程序,Java程序从一开始运行到终止的过程称为程序的生命周期,它和Java虚拟机的生命周期是一致的。

10.2 类的加载、连续和初始化

当Java程序需要使用某个类时,Java虚拟机会确保这个类已经被加载、连续和初始化。其中,连接的过程又被分为3个子过程。

加载:查找并加载类的二进制数据。

连接:包括验证、准备和解析类的二进制数据。

验证:确保被加载类的正确性。

准备:为类的静态变量分配内存,并将其初始化为默认值。

解析:把类中的符号引用转换为直接引用

初始化:给类的静态变量赋予正确的初始值。

所有Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用”时才初始化它们。Java虚拟机对类的使用分为两种:

主动使用

被动使用

10.2.1 类的加载

是指把类的.class 文件中的二进制数据读入到内存中,把它存放在运行时数据区的方法区中内,然后在堆区创建一个java.lang.Class对象。用来封装类在方法区内的数据结构。

Java 虚拟机能够从多种来源加载类的二进制数据,包括:

从本地文件系统中加载类的.class文件。

通过网络下载类的.class文件。

从ZIP、JAR或其它类型的归档文件中提取class文件

从一个专有数据库中提取class文件

把一个Java源文件动态编译为class文件

类的加载的最终产品是位于运行时数据区的堆区的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序提供类访问类在方法区的数据结构的接口。

类的加载是由类加载器完成的,类加载器可分为两种:

Java虚拟机自带的加载器:包括启动类加载器、扩展类加载器和系统类加载器。

用户自定义的类加载器:是java.lang.ClassLoader类的子类的实例,用户可以通过它来定制类的加载方式。

Java虚拟机允许类加载器在预料某个类将要被使用时,就预先加载它,如果在预先加载过程中遇到class文件缺失或存在错误,类加载器必须等到程序首次主动使用该类时才报告错误(抛出一个LinkageError实例)。如果一个类一直没有被程序主动使用,那么类加载器将不会报错。

10.2.2 类的验证

当类被加载后,就进入连接阶段,连接就是把已经读入到内存的类的二进制数据合并到虚拟机的运行环境当中。连接的第一步是类的验证。作用是:保证被加载的类的正确性。并且能与其它类协调一致。

如果Java虚拟机检查到错误,就会抛出相应的Error对象。

类的验证主要包含以下内容:

类文件的结构检查:确保类文件遵从Java类文件的固定格式。

语义检查:确保类本身符合Java语言的语法规定。

字节码检查:确保字节码流可以被Java虚拟机安全的执行。字节码流代表Java方法(包括静态方法和实例方法),它是由被称为操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。字节码验证步骤会检查每个操作码是否合法,即是否有着合法的操作数。

二进制兼容的验证:确保相互引用的类之间步调一致。

10.2.3 类的准备

在准备阶段,Java虚拟机为类的静态变量分配内存,并设置默认的初始值。

10.2.4 类的解析

在解析阶段,Java虚拟机会把类的二进制数据中的符号引用替换为直接引用。

10.2.5 类的初始化

在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在程序中,静态变量的初始化有两种途径:

在静态变量的声明处进行初始化。

在静态代码块中进行初始化。

静态变量的声明语句,以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行它们。

Java虚拟机初始化一个类包含以下步骤:

假如这个类还没有被加载和连接,那就先进行加载和连接。

如果类存在直接的父类,并且这个父类还没有被初始化,那么就先初始化直接的父类。

如果类中存在初始化语句,那么就依次执行这些初始化语句。

10.2.6 类的初始化的时机

Java虚拟机只有在程序首次主动使用一个类或接口时才会初始化它,只有六种活动被看作是程序对类或接口的主动使用:

创建类的实例。(包括用new语句创建实例,或者通过反射、克隆及反序列化手段来创建实例)

调用类的静态方法。

访问某个类或接口的静态变量,或者对该静态变量赋值。

调用JavaAPI中某些反射方法。

初始化一个子类。

Java虚拟机启动时被标明为启动类的类

类的初始化的时机:

对于final类型的静态变量,如果在编译时就能计算出变量的取值,那么这种变量被看作编译时常量。Java程序中对类的编译时常量的使用,被看作是对类的被动使用,不会导致类的初始化。

对于final类型的静态变量,如果在编译时不能计算出变量的取值,那么程序对类的这种变量的使用,被看作是对类的主动使用,会导致类的初始化。

只有当程序访问静态变量或静态方法的确在当前类或接口中定义时,才可以看作是对类的主动使用。

调用ClassLoader类的loadClass()方法加载一个类,并不是对类的主动使用,不会导致类的初始化。

10.3 类加载器

类加载器用来把类加载到Java虚拟机中。

Java虚拟机自带以下几种加载器:

根(Bootstrap)类加载器:该类加载器没有父加载器。负责加载虚拟机的核心类库。如java.lang.*。根类加载器的实现依赖于底层操作系统,属于虚拟机实现的一部分,它并没有继承java.lang.ClassLoader类。

扩展(Extension)类加载器:它的父加载器是根类加载器。0.+-

系统(System)类加载器:也称为应用类加载器,它的父加载器为扩展类加载器。

除了以上虚拟机自带的加载器,用户还可以定制自己的类加载器(User-defined Class Loader)。Java提供了抽象类java.lang.ClassLoader,所有用户自定义的加载器应该继承ClassLoader类。

10.3.1 类加载的父亲委托机制

在父亲委托机制中,各个加载器按照父子关系形成了树形结构,除了根类加载器以外,其余的类加载器都有且只有一个父加载器。

加载器之间的父子关系实际上是指加载器对象之间的包装关系,而不是类之间的继承关系。一对父子加载器可能是同一个加载器类的两个实例,也可能不是。

父类委托机制的优点是能提供软件系统的安全性。因为在此机制下,用户自定义的类加载器不可能加载应该由父加载器的可靠类,从而防止不可靠甚至恶意的代码替代由父加载器的可靠代码。

命名空间:

每个类加载器都有自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成。在同一个命名空间中,不会出现类的完整名字。相同的两个类。

运行时包

由同一个类加载器加载的属于相同包的类组成了运行时包,决定两个类是不是属于同一个运行时包,不仅要看它们的包名是否相同,还要看定义类加载器是否相同。只有属于同一运行时包的类才能互相访问包可见的类和类成员。

10.3.2 创建用户自定义的类加载器

要创建用户自己的类加载器,只需扩展java.lang.ClassLoader类,然后覆盖它的findClass方法,该方法根据参数指定的类的名字,返回对应的Class对象的引用。

10.3.3URLClassLoader类

在JDK的java.net 包中,提供了一个功能比较强大的URLClassLoader类,它拓展了ClassLoader类。它不仅能从本地文件系统加载类,还可以从网上下载类。Java程序可以直接用URLClassLoader类作为用户自定义的类加载器。

10.4 类的卸载

由Java虚拟机自带的类加载器所加载的类,在虚拟机的声明周期中,始终不会被卸载。由用户自定义的类加载器所加载的类是可以被卸载的。

标签:初始化,Java,静态,虚拟机,程序,面向对象编程,声明,加载

来源: https://www.cnblogs.com/codelions/p/13549301.html

java class对象创建时机_Java面向对象编程-类的声明周期相关推荐

  1. java类声明语句_Java面向对象编程-类的声明周期

    第十章 类的生命周期 10.1 Java虚拟机及程序的生命周期 当通过java命令运行一个Java程序时,就启动了一个Java虚拟机进程.Java虚拟机进程从启动到终止的过程,称为Java虚拟机的生命 ...

  2. java封装例题_java面向对象编程类的封装接口和基本类库练习题

    面向对象编程基本知识练习 一.判断题 1.不需要定义类,就能创建对象.() 2.构造方法用于给类的 private 实例变量赋值.() 3.对象一经声明就可以立即使用.() 4.在定义变量和方法时,必 ...

  3. java 给对象创建实例_Java中创建(实例化)对象的五种方式

    Java中创建(实例化)对象的五种方式1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运用反 ...

  4. java面相对象的关键字_Java面向对象关键字有哪些?

    面向对象的特征:封装.继承.多态 Java的关键字: 1)48个关键字:abstract.assert.boolean.break.byte.case.catch.char.class.continu ...

  5. Java基础学习——第六章 面向对象编程(下)

    Java基础学习--第六章 面向对象编程(下) 一.关键词:static 1. static关键字的引入 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new ...

  6. 第2课第3节_Java面向对象编程_继承性_P【学习笔记】

    摘要:韦东山android视频学习笔记  面向对象程序的三大特性之继承性:继承性的主要作用就是复用代码.继承性也有一定的限制,如图一 图一 1.我们在第2课第2节_Java面向对象编程_封装性_P 中 ...

  7. python多个对象调用类方法、且之间有联系_趣味解读Python面向对象编程 (类和对象)...

    一.面向对象简介 考虑现实生活中,我们的思维方式是放在学生这个个人上,是学生做了自我介绍.而不是像我们刚刚写出的代码,先有了介绍的行为,再去看介绍了谁. 用我们的现实思维方式该怎么用程序表达呢? 面向 ...

  8. 面向对象编程——类和对象

    面向对象编程 类和对象 类(Class):用来描述具有相同属性和方法的对象的集合 class Student:name='stu'#属性def say(self):#方法print("hel ...

  9. python面向对象图片_趣味解读Python面向对象编程 (类和对象)

    一.面向对象简介 考虑现实生活中,我们的思维方式是放在学生这个个人上,是学生做了自我介绍.而不是像我们刚刚写出的代码,先有了介绍的行为,再去看介绍了谁. 用我们的现实思维方式该怎么用程序表达呢?面向过 ...

最新文章

  1. 编程小问题系列(2)——为什么WPF里MediaElement等视频控件不起作用
  2. 第十七章 Python网络编程
  3. Java引入import其它目录的自定义包或java源文件
  4. Symfony2 生成应用包
  5. VHDL中的左移函数
  6. java:数据库连接池
  7. python穷举法_python 穷举指定长度的密码例子
  8. Leetcode 刷题笔记(十七) —— 二叉树篇之公共祖先问题
  9. 玩转大数据系列之一:数据采集与同步
  10. CMake的安装(超级详细)
  11. 武田宣布发表ICLUSIG(R) (ponatinib)枢纽性2期PACE血液病试验的终局数据
  12. Ti杯电子竞赛前期准备工作
  13. 使用阿里云Maven仓库
  14. HTTP抓包和Python爬虫获取7天酒店免费房信息
  15. kettle-xml输入
  16. 白嫖阿里-----搭建个人服务
  17. circos 中堆积柱状图的画法
  18. 营销思维篇:透漏22个我赚钱的小秘密
  19. .properties文件加载失败
  20. excel html 查询,html 连接 excel表格数据库数据-利用EXCEL表格为数据库制作查询网页...

热门文章

  1. 如何自动将AI Studio中的GIF文件上载到CSDN?
  2. 微型角度编码器 : KYTB-1503-1024
  3. 上海海事大学百度智慧交通车模介绍
  4. DAC输出波形的最大频率是多少?
  5. 参赛队员对于第十六届全国大学智能车竞赛的建议-05月
  6. 关于建立智能车竞赛开发资源中心的汇报PPT
  7. 这些建议需要竞赛组委会酌情考虑
  8. 服务器免密码传输文件,CentOS7,使用 scp 命令, ssh 连接方式,免密码传输文件到远程服务器,免密执行远程服务器上的 shell 脚本...
  9. 商城模板网站html5手机端_网站建设中,pc端与手机移动端设计一样吗
  10. python实操培训_python实训day1