一、概要:

类的生命周期从类的 加载、连接、初始化 开始,到类的 卸载结束;

二、几个阶段:

加载:查找并加载类的二进制数据。(把类的.class文件的二进制数据读入内存,存放在运行时数据区的方法区;类加载的最终结果是产生 堆区中描述对应类的Class对象);

连接:包括验证、准备和解析三个子阶段;

   验证:确保补加载类的正确性;

   准备:为类的静态变量分配内存,并设定默认值;

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

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

  

类的加载时机:并不需要等到某个类被主动使用时才加载,虚拟机会预测某个类将要被使用就加载它;

类的初始化时机:

  a. 创建类(new、反射、克隆、反序列化)

  b. 使用静态方法、非静态变量

  c. Class.forName("ATest");  获取描述类的Class对象;

  另:初始化子类,父类被先初始化。虚拟机的启动类,使用命令 java Sample(也算是创建类);

  注:

    使用能在编译期能得知的final static修饰的常量,不会导致类的初始化;

    public static final int a = 2*3;//编译时常量,不会导致类初始化;

    public static final int a b = (int)(Math.random()*10)/10+1; // 不是编译时常量,会初始化;

    只有当程序访问的静态变量或静态方法的确在当前类或接口中定义时,才可以看作是对类或接口的主动使用;(如用子类引用调用父类静态方法或变量,只会初始化父类)

    调用ClassLoader.loadClass()方法加载一个类时,只会加载,但不会初始化;

子类父类初始化过程:

先对这个类进行加载和连接-> 如果有直接父类,先加载连接初始化这个父类->重复以上步骤直到所有父类初始化,初始化当前类;

(先加载连接当前类,再加载连接初始化父类,再初始化当前类)

class Base {
static {
System.out.println("init Base");
}
} class Sub extends Base {
static {
System.out.println("init Sub");
}
} public class ATest extends Sub {
static {
System.out.println("init ATest");
} public static void main(String args[]) {
System.out.println("main methos");
}
}
结果:
init Base
init Sub
init ATest
main methos

三、类加载器

  除了Java虚拟机自带的根类加载器以外,其余的类加载器有且只有一个父加载器;

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

  根(Bootstrap)类加载器:没有父类加载器。负责加载虚拟机核心类,sun.boot.class.path路径下类库,java.lang.*; 实现依赖于底层操作系统,没有继承java.lang.ClassLoader;

  扩展(Extension)类加载器:父加载器为根加载器;加载java.ext.dirs下的类库 和 JDK目录下jre/lib/ext目录下类库;继承于java.lang.ClassLoader;

  系统(System)类加载器:也称应用类加载器,父加载器为扩展类加载器;加载classpath路径下指定的类库;继承于java.lang.ClassLoader,也是自定义加载器的默认父类;

父亲委托机制:

  类加载过程中,会先从最顶层加载器(一般是根加载器)开始往下,先判断父类加载器能不能加载,能加载则往下传递返回加载的类;不能加载则继续往下判断,如果都不能加载,则会抛出ClassNotFoundException异常;

  加载器之间的父子关系实际上是指加载器对象之间的包装关系,而不是类之间的继承关系;

命名空间:

  命名空间由该加载器及所有父加载器所加载的类组成;

  唯一性:在同一个命名空间中,不会出现类的完整名字(包名+类名)相同的两个类;

  同一命名空间有以下关系:

    同一命名空间的类是相互可见的;(可见是指可以直接使用其类名,不可见的类之间可以通过反射来获取类信息);

    子加载器的命名空间所含所有父加载器的命名空间,所有子类加载器的类能看见父加载器的类;但父加载器不能看见子加载器的类;

运行时包:

  包名相同,且属于同一个类加载器;

  同一运行时包的类才能包可见;如用户自己定义了一个java.lang.Spy,并由自己定义的类加载器加载,由于java.lang.Spy和核心类库java.lang.*由不同的类加载器加载,它们不在同一运行时包,Spy不能访问java.lang.*下的包可见类;

用户自定义类加载器:

  扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法;

  可通过 this.getClass().getClassLoader()获取类对应的加载器

类的卸载:(清除对应类的Class对象 和 类的二进制数据结构)

  由Java虚拟自带的三个类加载器加载的类不能卸载;(虚拟机会始终引用这3个类加载器,类加载器中有一个集合,又会一直引用其加载的类的Class对象)

  用户自定义的类加载器加载的类可以被卸载;

  

  

整理自孙卫琴《Java面象对象编程》

Java类的加载与生命周期的更多相关文章

  1. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  2. JAVA类的加载、连接与初始化

    JAVA类的加载.连接与初始化 类的声明周期总共分为5个步骤1.加载2.连接3.初始化4.使用5.卸载 当java程序需要某个类的时候,java虚拟机会确保这个类已经被加载.连接和初始化,而连接这个类 ...

  3. 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

    目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...

  4. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...

  5. 透过现象看本质:Java类动态加载和热替换

    摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...

  6. Java类的加载、链接和初始化

    一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...

  7. java 类的加载,链接,初始化

    本篇的话题,讨论Java类的加载.链接和初始化.Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象.一个Java类从字节代码 ...

  8. 【Java基础】Java类的加载和对象创建流程的详细分析

    相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下. 实例问题 实例代码 Parent类 package ...

  9. Java类的加载和对象创建流程的详细分析

    相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下: package com.test; public ...

随机推荐

  1. 写在php设计模式前

    在学校写代码的时候,看过许多代码,跟着学长学过一段时间.找工作的时候由于种种原因,从事于本专业, 最近重拾php,充充电,找个好工作. 以前项目中设计模式用的比较多的也就是单例模式,看书中回顾写过的代 ...

  2. linux中read用法

    read在while中的经常用法: root@ubuntu:/var/lib/logrotate :: # cat /etc/cron.daily/logrotate #!/bin/sh # Clea ...

  3. 使用Powermock和mockito来进行单元测试

    转载:http://blog.csdn.net/u013428664/article/details/44095889 简介 Mockito是一个流行的Mocking框架.它使用起来简单,学习成本很低 ...

  4. 好工具MyEclise2016 CI下载

    地址:http://pan.baidu.com/s/1gfBw9Ab 安装后,点开crack目录,按步骤走. 下面是我安装成功的画面.

  5. java类中,成员变量赋值第一个进行,其次是静态构造函数,再次是构造函数

    如题是结论,如果有人问你Java类的成员初始化顺序和初始化块知识就这样回答他.下面是代码: package com.test; public class TestClass{ // 成员变量赋值第一个 ...

  6. 【秀优越(xie e)】原来出题也能够这么恶心。

    通过邪恶的数据范围和数据限制居然能够把一道传统题出成题答2333. 诶毕竟内部互測,题目就不往上贴了. 特殊限制 - - - 题目作废.输出M行"Orz  PoPoQQQ" - M ...

  7. [Android]egit取消文件版本号控制

    开发项目,多人合作开发变得越来越重要了,在此同一时候,使用git作为协同工具也是越来越多.在此.介绍一下egit取消文件版本号控制的方法. (egit即为eclipse中的git插件) 1.打开Nav ...

  8. C#按指定长度分割字符串

    C#按指定长度分割字符串   这几天学习分析声音的波形数据,接收到的是十六进制的数据,需要将数据转换成十进制再绘图,这个过程涉及到字符串的分割,正好可以促进自己对C#相关知识的学习.说到分割字符串,我 ...

  9. java变参

    java变参是通过数组来实现的 Object[] addAll(Object[] array1, Object... array2)和Object[] addAll(Object[] array1, ...

  10. 【Python基础】之for循环、数组字典

    一. for循环实例 1.循环字符串 Python Shell: for i in "hello": print(i) h e l l o 2.循环数组Python Shell: ...