使用某个类是发生的事情

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

加载:将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. 【maven】 在 MyEcplise上使用maven搭建Web项目

    二.在My Ecplise上使用Maven搭建Web项目 1.新建一个maven项目   2.create一个简单的骨架 3.就像在ecplise中一样设置项目的以下配置   4.新创建的项目结构如下 ...

  2. 记录linux /bin被误删除的解决过程

    1.事因: 执行shell测试时,shell中rm -rf $path/* 变量$path为空,结果执行的命令是rm -rf / 事发时及时ctrl+c中断,导致只有/bin /boot目录删除 2. ...

  3. 第二个div+css前端项目

    先展示效果图: 为了看全景,截图有点挫.实际效果比这个好一点. 通过 text-overflow可以隐藏多出的文字,而不会吧把div撑开或者溢出. html代码: <!DOCTYPE html& ...

  4. ASP.NET中Url编码解码

    今天遇到Url编码解码的问题,纠结了一天的时间,结果上网一查才发现太二了我们. 同事写的代码把url用HttpUtility.UrlEncode编码和解码了,本地测试没有问题,部署到服务器上就提示转码 ...

  5. SpringJMS解析1-使用示例

    Spring配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h ...

  6. poj2385 dp(递推)

    题目链接 :http://bak3.vjudge.net/contest/136499#problem/D 题意: //转移方程dp[i][j]=max(dp[i-1][j],dp[i-1][j-1] ...

  7. 《DSP using MATLAB》为什么要z变换?

    书中截图

  8. LCS POJ 1458 Common Subsequence

    题目传送门 题意:输出两字符串的最长公共子序列长度 分析:LCS(Longest Common Subsequence)裸题.状态转移方程:dp[i+1][j+1] = dp[i][j] + 1; ( ...

  9. adams/car 怎么进入template builder模块

    打开C:\Documents and Settings\Administrator文件夹下的acar.cfg文件,将 Desired user mode (standard/expert)ENVIRO ...

  10. data.table包

    data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...