昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解。

这里我先把昨天的两份代码贴过来,重新看下:

class Singleton
{
private static Singleton singleton = new Singleton(); //第一份代码的位置
public static int counter1;
public static int counter2=0;
private static Singleton singleton = new Singleton();//第二份代码的位置 private Singleton(){
counter1++;
counter2++;
} public static Singleton getInstance(){
return singleton;
}
} public class Demo
{
public static void main(String[] args){
Singleton singleton=Singleton.getInstance();
System.out.println("counter1:"+singleton.counter1);
System.out.println("counter2:"+singleton.counter2);
}
}

第一份代码执行结果:

第二份代码执行结果:

类是如何被加载的

让我们再来回顾下上篇文章的加载顺序

我们知道Java虚拟机为类的静态变量分配内存,并设置默认的初始值实在准备阶段开始的,这里所设置的初始值通常情况下是类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。有很多人还是不太明白默认零值和显示赋值到底是什么意思,下面我们距离来说:

public class Sample{
private static int a=1;
private static int b;
}

上面的代码在经过了准备阶段后的结果是:

a=0;
b=0;

大家可能对b=0没有任何疑问,而a=0;就是上面说的“类型默认的零值”,也就是说准备的阶段等号右边的1并不会赋值给a,不知道这么解释大家能不能明白,而类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量 赋予正确的初始值。

private static int a=1; 表示a被显式初始化成1;
private static int b; 这里的b并没有被显式初始化,所以此时b的值仍然为0;

案例分析

好了,说了这么多开始分析案例,我们知道类是自上而下执行的,所以第一份代码解析如下

  1. 当Singletom类在准备阶段,由于只是分配数据类型默认值,所以此时的counter1=0、counter2=0;
  2. 当Singletom类在初始化阶段,1调用了Singleton的实例并对counter1和counter2分别进行了++操作,所以此时的counter1=1,counter2=1,由于2中未对counter1进行显式初始化,所以此时的counter1仍然保留值1,而counter2被显式赋值成0,所以counter2在初始化阶段又被改为0
  3. 在经过了准备、初始化阶段后的最终结果就变成了counter1:1、counter2:0

第二份代码是将1->2->3的顺序修改为2->3->1,我们按着上面的思路重新分析发现很清晰的就知道了结果

准备阶段没有任何变化,counter1=0、counter2=0;

初始化阶段,counter1没有被显式赋值,所以counter1仍然保留值0,counter2被显式赋值为0,所以counter2=0,到第三步时调用了Singleton()方法,此时执行了++操作

最终结果 counter1:1、counter2:1

深入java虚拟机学习 -- 类的加载机制(续)的更多相关文章

  1. 深入java虚拟机学习 -- 类的加载机制

    当看到"类的加载机制",肯定很多人都在想我平时也不接触啊,工作中无非就是写代码,不会了可以百度,至于类,jvm是怎么加载的我一点也不需要关心.在我刚开始工作的时候也觉得这些底层的内 ...

  2. 深入java虚拟机学习 -- 类的加载机制(三)

    类的初始化时机 在上篇文章中讲到了类的六种主动使用方式,反射是其中的一种(Class.forName("com.jack.test")),这里需要注意一点:当调用ClasLoade ...

  3. 深入java虚拟机学习 -- 类的加载机制(四)

    类加载的命名空间 每个类加载器都有自己的命名空间,命名空间由所有以此加载器为初始类加载器的类组成,不同命名空间的两个类是不可见的,但只要得到类所对应的Class对象的refrence(反射),还是可以 ...

  4. Java基础_类的加载机制和反射

    类的使用分为三个步骤: 类的加载->类的连接->类的初始化 一.类的加载 当程序运行的时候,系统会首先把我们要使用的Java类加载到内存中.这里加载的是编译后的.class文件 每个类加载 ...

  5. 深入java虚拟机学习 -- 类的卸载

    类的生命周期 在开始本节之前让我们再来回顾下类的生命周期 没看过前6个过程的同学建议从头看下<深入java虚拟机学习 -- 类的加载机制>,这里就不再过多介绍了,着重说下类的卸载 类的卸载 ...

  6. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  7. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...

  8. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  9. jvm系列 (五) ---类的加载机制

    类的加载机制 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 jvm系列 (四) ---强.软.弱.虚引用 我的博客目录 什么是类 ...

随机推荐

  1. jQuery——动态给表格添加序号

    摘录自:http://www.cnblogs.com/picaso/archive/2012/10/08/2715564.html 很多时候遇到需要对表格动态操作,而且一般都会有表格的序号,但是有时候 ...

  2. docker 安装 msyql

    **************************************************************************************************** ...

  3. Python装饰器小代码

    # coding=utf-8import timedef outer(fun): def inner(): start = time.time() fun() runtime = time.time( ...

  4. python3 第十八章 - 迭代器与生成器

    1.迭代器(Iterator) 迭代是访问集合元素的一种方式 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 迭代器 ...

  5. .NET 异步多线程,Thread,ThreadPool,Task,Parallel,异常处理,线程取消

    今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一 ...

  6. svn一整套使用,从下载到整个服务器搭建完成的详细说明

    SVN服务器的本地搭建和使用 Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上 ...

  7. 动态库Link error 一种可能

    一般出现link error都是链接时找不到对应函数. 前些天出现这种错误,我反复地检查,都发现动态库里明确的是有对应函数的. 代码里有这样一句#pragma comment(lib,"li ...

  8. 布隆过滤器(BloomFilter)持久化

    摘要 Bloomfilter运行在一台机器的内存上,不方便持久化(机器down掉就什么都没啦),也不方便分布式程序的统一去重.我们可以将数据进行持久化,这样就克服了down机的问题,常见的持久化方法包 ...

  9. kali初探:root用户打开wireshark打开失败

    启动wireshark后,报错: 该界面提示在init.lua文件中使用dofile函数禁用了使用超级用户运行wireshark.这是因为wireshark工具是使用Lua语言编写的,并且在kali ...

  10. bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]

    4813: [Cqoi2017]小Q的棋盘 题意: 某poj弱化版?树形背包 据说还可以贪心... #include <iostream> #include <cstdio> ...