Java类加载与初始化

原创 2016年05月31日 15:42:35


一、类的生命周期

1虚拟机的加载机制

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

类从被加载到虚拟机内存中开始,直到卸载出内存为止,它的整个生命周期包括

 

 

加载(即生成Class对象)->链接(验证+准备+解析)(即相当于jvm编译,会给类静态变量默认值)->初始化(使用前的准备,也是部分初始化JAVA代码开始,如构造函数,和类静态变量的初始值)->使用->卸载

其中验证、准备、解析统称为连接。加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类的加载过程必须按照这个顺序来按部就班地开始,而解析阶段则不一定,它在某些情况下可以在初始化阶段后再开始。

(2)类的加载时机

虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握。

(3)类的初始化时机

在类初始化之前要完成类的加载和连接。类初始化的时机,首次主动使用该类时会触发初始化,

1、遇到new、getstatic、putstatic、invokestatic这四条字节码指令的时候。

     a .用new实例化一个类时

  b.读取或者设置类的静态字段时(不包括被final修饰的静态字段,因为他们已经被塞进常量池了)

  特殊情况:public static final int A = 4 + new Random().nextInt(10);//静态final   变量在编译时不定的情况

  c.以及执行静态方法的时候。

2、使用java.lang.reflect进行反射调用的时候。

3、当初始化一个类的时候,发现其父类还没有初始化,那么先去初始化它的父类。

4、当虚拟机启动的时候,需要初始化main函数所在的类。

以上情况称为称对一个类进行 “主动引用” ,除此种情况之外,均不会触发类的初始化,称为 “被动引用”

接口的加载过程与类的加载过程稍有不同。接口中不能使用static{}块。当一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有真正在使用到父接口时(例如引用接口中定义的常量)才会初始化。

二、对类的“被动引用”(类不会被初始化)

1通过子类引用父类的静态字段,父类会初始化,不会导致子类的初始化


class SuperClass{
    static{
        System.out.println("父类初始化");
    }
    public static int value=100;
}
 
class SubClass extends SuperClass{
    static{
        System.out.println("子类初始化.");
    }
}
 
public class Test1{
    public static void main(String[]args){
        System.out.println(SubClass.value);
    }
    
}

输出结果为:

父类初始化

100

2通过数组引用来引用类,不会触发此类的初始化

class SuperClass{
    static{
        System.out.println("父类初始化");
    }
    public static int value=100;
}
 
public class Test1{
    public static void main(String[]args){
         SuperClass[] s = new SuperClass[5];
    }
    
}

无结果输出,就是不会对SuperClass进行初始化

(3)常量在编译阶段会被存入调用类的常量池中,本质上并没有引用到定义常量类,所以自然不会触发定义常量的类的初始化

class ConstClass
{
    static{
        System.out.println("ConstClass init.");
           }
public final static Stringvalue="hello world";
 }
 
public class Test1
{
    public static void main(String[]args){
     System.out.println(ConstClass.value);
}


输出结果:hello world

只调用ConstClass类中的常量 不会初始化ConstClass类。

三、类在JVM中的工作原理

(1)类的加载

从字节码二进制文件——.class文件将类加载到内存,从而达到类从硬盘上到内存上的一个迁移,所有的程序必须加载到内存才能工作。

将内存中的class放到运行时数据区的方法区内,之后在堆区建立一个java.lang.Class对象,用来封装方法区的数据结构。类加载的最终产物就是堆中的一个java.lang.Class对象。

(2)连接

    1)验证:出于安全性的考虑,验证内存中的字节码是否符合JVM的规范,类的结构规范、语义检查、字节码操作是否合法、这个是为了防止用户自己建立一个非法的XX.class文件就进行工作了,或者是JVM版本冲突的问题,比如在JDK1.7下面编译通过的class(其中包含注解特性的类),是不能在JDK1.4的JVM下运行的。

 

 2)准备:将类的静态变量进行分配内存空间、初始化默认值。注意是初始值。

默认的初始值类型如下:

整数类型(byte、int、short、long):0

浮点类型(float、double):0.0

字符类型(char):(‘\u0000

布尔类型(boolean):false

引用类型(类、接口、数组):null

3)解析:把类的符号引用转为直接引用

(3)类的初始化

版权声明:转载请标明出处

浅谈Java类加载的初始化阶段

类加载的初始化阶段对类变量赋予正确的值。主要有两种初始化方式,一种是通过类变量初始化语句;一种是静态初始化语句。如下述代码所示,前者是类变量初始化语句,后者是静态初始化语句。...
  • lincolnmi
  • lincolnmi
  • 2016年01月18日 22:04
  • 2366

java的各种加载和初始化的详细过程

一、什么时候加载和初始化 1、类什么时候加载 类的加载是通过类加载器(Classloader)完成的,它既可以是饿汉式[eagerly load](只要有其它类引用了它就加载)加载类,也可以是懒加载...
  • w1lgy
  • w1lgy
  • 2016年12月22日 23:56
  • 710

Java类的加载和初始化顺序分析

不再一一叙述java中的各种定义和规定, 这里就是举了两个例子,详细阐述,java代码运行时,成员变量和构造函数的加载和执行顺序。 package com.gt.world.oa.aaa;...
  • haorengoodman
  • haorengoodman
  • 2014年04月03日 13:58
  • 3179

Java类加载器:静态变量初始化

先看两个例子: package wh; class Singleton{ public static Singleton singleton = new Singleton(); publi...
  • woshiwanghao_hi
  • woshiwanghao_hi
  • 2015年11月02日 21:10
  • 1036

类的加载、连接与初始化过程的详细分析(上)

前面一个博客文章介绍过了类从加载到可以被使用经过了加载、连接、初始化三个过程,下面对每个过程所发生的事情做详细分析。 一、类加载阶段         1.类加载方式         类的加载指...
  • sunfeizhi
  • sunfeizhi
  • 2015年12月20日 22:40
  • 1496

Java类加载过程后,成员变量的初始化。

Java类的加载和成员变量初始化,创建对象的顺序。 class X { Y b=new Y(); X() { System.out.println("X"); } } class Y...
  • xxxcsdnblog
  • xxxcsdnblog
  • 2015年06月23日 17:29
  • 1544

【JVM】类加载、连接和初始化过程

程序运行时,加载类主要经过3个阶段分别是类的加载,连接和初始化。分别介绍一下这三个过程。 一、加载类的加载指的是将类的.class文件中二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆...
  • wangyy130
  • wangyy130
  • 2016年08月04日 14:35
  • 1346

JAVA之类加载机制与反射(一)

类的加载、连接和初始化 系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类。 JVM和类 当调用java命令运行某个Java程序时,该命令会启动一个Java虚拟机进程,不管...
  • diaotai
  • diaotai
  • 2016年10月16日 16:42
  • 751

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

Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类 的对象。一个Java类从字节代码到能够在JVM中被使用,需要经过加载、链接...
  • waysoflife
  • waysoflife
  • 2016年07月14日 11:04
  • 752

java类加载与初始化

目录类加载器 动态加载 链接 初始化 示例类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用。 每个类编译后产生一个Cl...
  • qq_34515159
  • qq_34515159
  • 2017年07月18日 17:32
  • 104
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java类加载与初始化
举报原因:
原因补充:

(最多只允许输入30个字)