使用某个类是发生的事情

加载->链接(验证、准备、解析)->初始化->可以使用

加载:将class文件字节码内容加载到内存当中,并将这些静态数据转换成方法区中的运行时数据结构

在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。

链接:将java类的二进制代码合并到jvm的运行状态之中的过程

  验证:确保加载的类信息符合jvm的规范,没有安全方面的问题。(确保加载的二进制代码不会损坏jvm)。

  准备:正式为类变量(static变量,此时初始化为0,在后续的初始化时会将用户的初始化值赋给类变量)分配内存并设置变量初始值的阶段,这些内存都将在方法区中进行分配。

  解析:虚拟机常量池内的符号引用替换为直接引用的过程。(注:常量池内的内容包括类名、类内部的变量名、字符串常量等等)

初始化:

初始化阶段是执行类构造器<clinit>()方法的过程,类构造器<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的(简言之,就是合并类的静态变量和静态代码块,形成类构造器进行执行)。

当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化

虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。

当访问一个java类的静态域时,只有真正声明这个域的类才会被初始化。

如下代码说明了初始化阶段为执行类构造器<clinit>()的过程,即类构造器的执行是先于类的构造方法的。

class A {
public static int width = 100; static {
System.out.println("before 静态初始化类A"+A.width);
width = 300;
System.out.println("after 静态初始化类A"+A.width);
} public A(){
System.out.println("创建A类的对象");
}
} public class Demo { public static void main(String[] args) {
A a = new A();
System.out.println(A.width); }
}

  可以看到类构造方法<clinit>()的执行在构造器之前。

下面代码则说明了当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

package com.test;

class A_Father{
static {
System.out.println("静态初始化A_Father");
}
} class A extends A_Father{
public static int width = 100; static {
System.out.println("before 静态初始化类A"+A.width);
width = 300;
System.out.println("after 静态初始化类A"+A.width);
} public A(){
System.out.println("创建A类的对象");
}
} public class Demo { public static void main(String[] args) {
A a = new A();
System.out.println(A.width); }
}

  看如下的代码分析输出

package com.test;

class A_Father{
static {
System.out.println("静态初始化A_Father");
}
} class A extends A_Father{
public static int width = 100; static {
System.out.println("before 静态初始化类A"+A.width);
width = 300;
System.out.println("after 静态初始化类A"+A.width);
} public A(){
System.out.println("创建A类的对象");
}
} public class Demo {
static{
System.out.println("静态初始化Demo");
} public static void main(String[] args) {
System.out.println("Demo的main方法");
A a = new A();
System.out.println(A.width);
A a2 = new A(); //java.lang.Class<A> aclass = A.class;
//Class aclass2 = A.class;
}
}

  输出如下:

静态初始化Demo
Demo的main方法
静态初始化A_Father
before 静态初始化类A100
after 静态初始化类A300
创建A类的对象
300
创建A类的对象

首先程序执行时要加载public的Demo类,初始化类(执行类构造方法)于是打印了“静态初始化Demo”,类初始化完成后进入方法调用,即main方法中,输出“Demo的main方法”,此时执行下一句  A a = new A();  因为A类此时尚未加载,所以首先要加载类A,然后链接初始化,初始化时发现A还有个父类没有加载呢,于是又去加载父类,链接初始化父类,打印了消息“静态初始化A_Father”,父类初始化完成了,此时类A的初始化开始,于是打印了“before 静态初始化类A100” 和“after 静态初始化类A300”,到这个时候,类已经全部加载到内存当中了,于是可以创建A的对象了,于是打印“创建A类的对象”,执行打印语句输出“300”,最后又创建了A的一个对象,但是由于类已经加载过了,所以只会调用类的构造器输出“创建A类的对象”,说明了类的加载只有一次,而类的实例化可以有多次。

关于类的加载有一个细节:

类的加载分为类的被动引用和类的主动引用,类的被动引用不会发生类的初始化,类的主动引用一定会发生类的初始化。

类的被动引用有

  1.当访问一个静态域时,只有真正声明这个域的类才会被初始化(通过子类引用父类的静态变量不会导致子类初始化,只有父类被初始化)

  2.通过数组定义类引用,不会触发此类的初始化。

  3.引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)

类的主动引用有

  1.new一个类的对象

  2.调用类额静态成员(除了final常量)和静态方法。

  3.使用java.lang.reflect包的方法对类进行反射调用

  4.当虚拟机启动,java Hello,则一定会初始化Hello类(直白的说就是先加载main方法所在的类)

  5.当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类。

测试代码:

package com.test;

class A_Father{
static {
System.out.println("静态初始化A_Father");
}
} class A extends A_Father{
public static int width = 100;
public static final int MAX = 100;
static {
System.out.println("before 静态初始化类A"+A.width);
width = 300;
System.out.println("after 静态初始化类A"+A.width);
} public static void test(){
System.out.println("静态方法");
} public A(){
System.out.println("创建A类的对象");
}
} class B extends A{
static {
System.out.println("静态初始化B");
}
} public class Demo {
static{
System.out.println("静态初始化Demo");
} public static void main(String[] args) throws ClassNotFoundException {
System.out.println("Demo的main方法");
//主动加载
//new A();
//System.out.println(A.width);
//A.test();
//Class.forName("com.test.A"); //被动加载
//System.out.println(A.MAX);
//A[] as = new A[10];
System.out.println(B.width); }
}

  

java类加载机制的更多相关文章

  1. Java 类加载机制

    类的加载: 类的初始化: 类什么时候才被初始化:1)创建类的实例,也就是new一个对象2)访问某个类或接口的静态变量,或者对该静态变量赋值3)调用类的静态方法4)反射(Class.forName(&q ...

  2. Java类加载机制深度分析

    转自:http://my.oschina.net/xianggao/blog/70826 参考:http://www.ibm.com/developerworks/cn/java/j-lo-class ...

  3. 理解Java类加载机制(译文)

    理解java类加载机制 你想写类加载器?或者你遇到了ClassCastException异常,或者你遇到了奇怪的LinkageError状态约束异常.应该仔细看看java类的加载处理了. 什么是类加载 ...

  4. 剑指Offer——知识点储备-故障检测、性能调优与Java类加载机制

    剑指Offer--知识点储备-故障检测.性能调优与Java类加载机制 故障检测.性能调优 用什么工具可以查出内存泄露 (1)MerroyAnalyzer:一个功能丰富的java堆转储文件分析工具,可以 ...

  5. 两道面试题,带你解析Java类加载机制

    文章首发于[博客园-陈树义],点击跳转到原文<两道面试题,带你解析Java类加载机制> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Gr ...

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

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

  7. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  8. Java类加载机制的理解

    算上大学,尽管接触Java已经有4年时间并对基本的API算得上熟练应用,但是依旧觉得自己对于Java的特性依然是一知半解.要成为优秀的Java开发人员,需要深入了解Java平台的工作方式,其中类加载机 ...

  9. Java类加载机制与Tomcat类加载器架构

    Java类加载机制 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...

  10. 带你解析Java类加载机制

      目录 Java类加载机制的七个阶段 加载 验证 准备(重点) 解析 初始化(重点) 使用 卸载 实战分析 方法论 树义有话说 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如 ...

随机推荐

  1. js实现上传图片及时预览

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  3. JDK BIO编程

    网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建 ...

  4. DSP using MATLAB 示例 Example3.10

    用到的性质 上代码: n = -5:10; x = rand(1,length(n)) + j * rand(1,length(n)); k = -100:100; w = (pi/100)*k; % ...

  5. 如何定义移动端字体Font-Family?

    1.对于IOS 手机系统,默认中文字体是Heiti SC.默认英文字体是Helvetica.默认数字字体是HelveticaNeue.无微软雅黑字体: 2.对于Android 手机系统,默认中文字体是 ...

  6. 用触发器来实现Oracle的自增长列

    1, 添加id列 -- ############################################### -- add ID column for XXXXXXTABLE -- #### ...

  7. 矩阵快速幂 ZOJ 3497 Mistwald

    题目传送门 题意:看似给了一个迷宫,每个点能传送到4个地方,问在P时间能否到达终点 分析:其实是一个有向图,可以用邻接矩阵存图,连乘P次看是否能从1到n*m,和floyd的传递背包思想一样 #incl ...

  8. Codeforces Round #337 (Div. 2)

    水 A - Pasha and Stick #include <bits/stdc++.h> using namespace std; typedef long long ll; cons ...

  9. HDU4888 Redraw Beautiful Drawings(最大流唯一性判定:残量网络删边判环)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4888 Description Alice and Bob are playing toget ...

  10. LightOJ1018 Brush (IV)(状压DP)

    题目大概说一个平面有n个灰尘,可以用一把刷子直直刷过去清理直线上的所有灰尘,问最少要刷几下才能清理完所有灰尘. 首先怎么刷其实是可以确定的,或者说直线有哪些是可以确定的,而最多就有C(n,2)条不一样 ...