使用某个类是发生的事情

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

加载:将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. Linux常用工具之XFTP、Xshell配置

    Xftp是一个基于 MS windows 平台的功能强大的SFTP.FTP文件传输软件.使用了 Xftp 以后,MS windows 用户能安全地在UNIX/Linux 和 Windows PC 之间 ...

  2. scrollview嵌套listview 滑动事件冲突的解决方法

    listView.setOnTouchListener(new View.OnTouchListener() {                            @Override       ...

  3. Android 自定义实现switch开关按钮

    前几天在看蘑菇街上有个开关按钮: 就在想是怎样实现的,于是反编译了它的源码,但是这时得到了下面的几张图片: 图片对应的名称: 无色长条:switch_frame; 白色圆点:switch_btn_pr ...

  4. [HTTP那些事]网络请求API

    在Android上,原生API有两个,HttpUrlConnection和HttpClient,它们对封装Socket进行封装,让HTTP请求变得简单.这应该也算框架吧? 想象下,如果没有HttpUr ...

  5. DOM--2 创建可重用的对象

    对象中包含的 分类(内置对象: 注意这些都是function:除了Function对象,实例都是object) Function对象 Function实例function 构造函数的function ...

  6. 仓库、超市、服装、食品、批发零售手持打印PDA开单器-现场无线开单扫描 无线传输电脑

    深圳浩瀚技是一家主要从事手持数据终端硬件.软件研究.销售服务为一体的高新企业公司.公司主要销售进销存等无线开单系统.工业级手持PDA,安卓数据采集器,RFID阅读器等设备.我们秉承“诚信.敏捷.繁荣” ...

  7. css3 -- 颜色与不透明度

    1.opacity: opacity的值会被它的所有子元素继承,也就是说不可能让一个元素比他的父元素更加不透明,但你可以让他变得更透明点 Firefox  Webkit  Opera支持,注意IE 2 ...

  8. Chage

    For many times,i've given my own a new lifestyle,such as don't stay up late,have breakfast......whil ...

  9. JS日期函数

    JS的日期函数有以下几个: getFullYear(); //获取当前年 getMonth(); //获取当前月,需要加1,而且只有一位数字,如果小于10需要前面加0 getDate(); //获取当 ...

  10. https://www.nginx.com/blog/introduction-to-microservices/

    https://www.nginx.com/blog/introduction-to-microservices/