在经过了前面的加载  和 连接分析之后,这一节我们进入重要的初始化分析过程:

一、认识初始化

初始化:这个似乎与上面的初始化为默认值有点矛盾,我们再看一遍:为累的静态变量赋予正确的初始值,上面是赋予默认值,这里是赋予正确的初始值,什么是正确的初始值,就是用户给赋予的值。我们来看一个例子

class Test{
private static int a = 1; }

我们知道,这个类加载好之后,a的值就是1,但实际是这样子的,类在加载的连接阶段,将a初始化为默认值0(int的默认值是0),然后在初始化阶段将a的值赋予为正确的初始值1. 我们看到最终a的值是等于1,但是实际的运行中是有一个将0赋予a的过程,这个过程放生在连接的准备阶段。类的初始化还有另外的一种形式,代码如下:

class Test{

private static int a ;

static{

a=1;

  }

}

这里强调一点,这个时候还是没有类的实例生成的,这点一定要注意!《深入java虚拟机第二版》里面有一个图阐述了对应的关系,如下:

静态变量的声明语句,以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行它们。

二、初始化步骤

1.假如这个类还没有被加载和连接,那就先进行加载和连接。【加载和连接执行完成后不一定会执行初始化,要符合主动使用才会进行初始化,否则只会执行加载和连接】
2.假如类存在直接的父类,并且这个父类还没有被初始化,那就先初始化直接的父类。
3.假如类中存在初始化语句,那就依次执行这些初始化语句。

三、主动使用和被动使用【初始化时机】

Java程序对类的使用方式可分为2种,主动使用和被动使用。所有的Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用时”才初始化他们。

主动使用的六种情况:

1.创建类的实例。

new Test();

2.访问某个类或接口的静态变量,或者对该静态变量赋值。

int b = Test.a;
Test.a = b;

3.调用类的静态方法

Test.doSomething();

4.反射

Class.forName(“com.mengdd.Test”);

5.初始化一个类的子类

class Parent{
}
class Child extends Parent{
public static int a = 3;
}
Child.a = 4;

6.Java虚拟机启动时被标明为启动类的类

java com.mengdd.Test

除了以上六种情况,其他使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化 (除了上述6种情况以外,都不会执行初始化,只会执行加载和连接)

这个时候我们再来看第一节学习中那段比较诡异的代码:

class Singleton{

    private static Singleton singleton=new Singleton();

    private static int counter1;

    private static int counter2 = 0;

    public Singleton() {

       counter1++;

       counter2++;

    }

    public static int getCounter1() {

       return counter1;

    }

    public static int getCounter2() {

       return counter2;

    }

    public static Singleton getInstance(){

       return singleton;

    }

}

public class ClassLoaderTest {

    @SuppressWarnings("static-access")

    public static void main(String[] args) {

       Singleton singleton=Singleton.getInstance();

       System.out.println("counter1:"+singleton.getCounter1());

       System.out.println("counter2:"+singleton.getCounter2());

       System.out.println(singleton.getClass().getClassLoader());

    }

}

我们调用Singleton singleton=Singleton.getInstance();调用Singleton的静态方法,相当于主动使用了类Singleton,因此Singleton被初始化!
当我们看到显示的是:

private static Singleton singleton=new Singleton();

    private static int counter1;

    private static int counter2 = 0;

这样的时候,顺序执行,先赋予初始值,singleton为null,counter1为0,counter2为0,然后顺序对singleton赋予正确的值newSingleton(),执行构造函数,counter1增加变为1,然后counter2变为1,然后继续执行初始化,将counter2赋值为正确的值,将counter2修改为0,因此运行结果是1、0

反过来

private static int counter1;

    private static int counter2 = 0;

    private static Singleton singleton=new Singleton();

先赋予初始值counter1为0,counter为0,singleton为null,然后对counter2赋值为正确的值,counter2为0,然后对singleton执行初始化赋予正确的值new Singleton(),执行构造函数,counter1为1,counter2为1,因此执行结果是1、1

到此,是不是感觉前面的问题豁然开朗了呢?

参考资料:

圣思园张龙老师深入Java虚拟机系列

JVM学习四:JVM之类加载器之初始化分析的更多相关文章

  1. jvm系列(四):jvm知识点总结

    原文链接:http://www.cnblogs.com/ityouknow/p/6482464.html jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 ...

  2. jvm学习006 jvm内存结构分配

    主要内容如下: JVM启动流程 JVM基本结构 内存模型 编译和解释运行的概念 一.JVM启动流程: JVM启动时,是由java命令/javaw命令来启动的. 二.JVM基本结构: JVM基本结构图: ...

  3. JVM学习笔记-JVM模型

    JVM学习笔记 == 标签(空格分隔): jvm 学习笔记全部来自于<深入理解java虚拟机>总结 jvm内存示意图 虚拟机栈(Java Virtual Machine Stacks): ...

  4. JVM学习三:JVM之类加载器之连接分析

    学习完类加载之加载篇后,让我们继续来看加载之连接,连接分为三个步骤:验证.准备和解析三步,我们将一一分析之. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 类加载完毕之后进入 ...

  5. JVM学习四:深入分析ClassLoader

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  6. JVM体系结构之二:类加载器之2:JVM 自定义的类加载器的实现和使用

    一.回顾一下jdk自带的类加载器: 1.java虚拟机自带的加载器     根类加载器(Bootstrap,c++实现)     扩展类加载器(Extension,java实现)     应用类加载器 ...

  7. 【JVM学习笔记】系统类加载器

    可以通过“java.system.class.loader"属性指定系统类加载器 默认情况下,该属性值为空: public class Test { public static void m ...

  8. 【JVM学习笔记】扩展类加载器

    扩展类加载器独有的特点,代码如下 public class Sample { } public class Test { static { System.out.println("Test ...

  9. JVM学习--(四)垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. stop the world 在介绍垃圾 ...

随机推荐

  1. Nodejs学习笔记(二)--- 操作MongoDB数据库

    最近看了一些关于mongodb的文章,然后就想知道nodeJS是怎么连接的所以我就尝试去了解了一波(这个菜鸟驿站这个网站还不错,虽然知识文档不是最新的,但是还是蛮好的: 顺便官网地址是这个哦:http ...

  2. springmvc 路由

    工作中MVC是较常使用的web框架,作为研发人员,也习惯了以编写Controller作为项目开始,写好了Controller和对应的方法,加上@RequestMapping注解,我们也就认为一切已经准 ...

  3. EF动态排序

    转载的代码,改天再研究 public PageData<T> FindAll(int PageIndex, int PageSize, Expression<Func<T, b ...

  4. 【第九周】psp

        代码累计 300+575+475+353+620=2223 随笔字数 1700+3000+3785+4210+4333=17695 知识点 java反射机制 数据库技术 动态规划算法 pyth ...

  5. 【BioCode】根据seq与位点信息截取窗口

    代码说明 sequence24371.txt 以上为所有氨基酸的编号,序列,与位点标记.根据标记为“1”的位点,截取窗口:如下(实验结果): 图示为一个窗口为12的蛋白质片段 2N+1=25: 实现代 ...

  6. Linux输入子系统:多点触控协议 -- multi-touch-protocol.txt768

    转自:http://blog.csdn.net/droidphone/article/details/8434768 Multi-touch (MT) Protocol --------------- ...

  7. BZOJ3884 上帝与集合的正确用法(欧拉函数)

    设f(n)为模n时的答案,由2k mod n=2k mod φ(n)+φ(n) mod n(并不会证),且k mod φ(n)=f(φ(n)),直接就可以得到一个递推式子.记搜一发即可. #inclu ...

  8. 洛谷 P3177 树上染色

    题面 题目要求将k个点染成黑色,求黑点两两距离及白点两两距离,使他们之和最大. 我们可以将距离转化为路径,然后再将路径路径拆分成边,就可以记录每条边被经过的次数,直接计算即可. 很简单对吧?那么问题来 ...

  9. P2762 太空飞行计划问题(网络流24题之一)

    题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的 ...

  10. [HNOI2006]最短母串问题 AC自动机

    题面:洛谷 题解: 如果我们对这些小串建出AC自动机,那么我们所求的大串就是要求满足遍历过所有AC自动机上的叶子节点,且经过步数最少的串.如果有多个步数相同的串,要输出字典序最小的串. 在AC自动机上 ...