`

Java类装载顺序

    博客分类:
  • java
阅读更多
.新版论坛系列介绍之二——功能介绍篇            2012 SDCC门票社区团购火热开启!            公告:CSDN博客频道博客搬家功能上线!
移动盛会强档来袭,参会套票全线秒杀!    没有重量只有质量:iPad版《程序员杂志》应用上线    “我最喜欢的技术博客”获奖公布!
Java类装载顺序 .
分类: Java 2008-05-29 13:46 141人阅读 评论(0) 收藏 举报
虽然没犯过「全世界所有男人都会犯的错误」,但是我倒是曾经犯了「全世界所有程序员都会犯的错误」。不管使用何种语言,全世界所有程序员都一定犯过这种错误,那就是: 太依赖编译器,却不知道编译器做了哪些事。
一般来说,越高阶的程序语言,会提供越多语法上的便利,以方便程序撰写,这就俗称为 syntactic sugar,我称其为「语法上的甜头」。虽说是甜头,但是如果你未能了解该语法的实质内涵,很可能会未尝甜头,却吃尽苦头。

下面是一个例子:

public class Singleton {

private static Singleton obj = new Singleton();

public static int counter1;
public static int counter2 = 0;

private Singleton() {
  counter1++;
  counter2++;
}

public static Singleton getInstance() {
  return obj;
}

}

public class MyMain {

public static void main(String[] args) {
  Singleton obj = Singleton.getInstance();
  System.out.println("obj.counter1=="+obj.counter1);
  System.out.println("obj.counter2=="+obj.counter2);
}

}

执行结果是:
obj.counter1==1
obj.counter2==0
你有没有被此结果吓一跳?乍看程序代码,你很可能会认为counter1和counter2的值一定 vbJ北方站长站
会相等,但执行结果显然不是如此。其实,程序1被编译后的程序应该等同于下面的程序

public class Singleton{

private static Singletonobj;
public static int counter1;
public static int counter2;

static {
  // 这就是class constructor
  // 在进入此class constructor之前,class已经被JVM配置好内存,
  //所有的static field都会被先设定为0,
  // 所以此时counter1和counter2都已经是0,且singleton为null

  //obj = new Singleton(),问题皆由此行程序产生
  // counter1不会在此被设定为0,counter2 = 0;
  // counter2再被设定一次0(其实是多此一举)
  obj = new SingletonExample();
  counter2 = 0; }

private Singleton() {
  // 这是instance constructor
  counter1++;
  counter2++;
}

public static Singleton getInstance() {
  return obj;
}

}

这是因为:当class具有static field,且直接在宣告处透过「=...」的方式设定其值时,编译器会自动将这些叙述依序搬到class constructor内。同样地,当class具有instance field,且直接在宣告处透过「=...」的方式设定其值时,编译器会自动将这些叙述依序搬到instance constructor内。 vbJ北方站长站
此程序在class constructor内,还未将static field初始化时(这时候,counter1和counter2都是0),就呼叫instance constructor,而instance constructor竟然还会去更动static field的值,使得counter1和counter2都变成1。然后instance constructor执行完,回到class constructor,再把counter2的值设为0(但是counter1维持不变)。最后的结果:counter1等于1,counter2等于0。

欲改正程序1,方法有三:
-方法一:将singleton field的宣告调到counter1与counter2 field之后。这是最好的作法。
-方法二:将counter2=0的宣告中,「=0」的部分删除。这种作法只有在希望
-方法三:将初始化的动作搬到class constructors内,自行撰写,而不依赖编译器产生。这是最保险的作法。
分享到:
评论

相关推荐

    java类装载

    java类装载介绍,介绍了java装载类的先后顺序

    Java虚拟机类装载:原理、实现与应用

    Java虚拟机类装载机制是Java运行环境的核心技术之一,它允许程序在运行时动态加载和使用类,极大地增强了软件的灵活性和可扩展性。本文主要探讨了类装载的原理、实现方式及其在实际应用中的作用。 首先,类装载的...

    Java虚拟机类装载.doc

    Java虚拟机类装载 Java虚拟机(JVM)的类装载是指将包含在类文件中的字节码装载到JVM中,并使其成为JVM的一部分的过程。Java虚拟机的类动态装载技术能够在运行时刻动态地加载或者替换系统的某些功能模块,而不影响...

    Java的类装载器和命名空间

    在学习过程中,可能会遇到一些混淆的问题,比如类装载器的委托模型、类的加载顺序以及如何自定义类装载器以加载非标准路径的类。理解这些概念有助于解决实际开发中遇到的类加载问题,例如,当需要加载外部库或者...

    websphere6,7上修改类装载顺序为应用程序优先

    "websphere6,7上修改类装载顺序为应用程序优先"这个话题涉及到如何调整WebSphere的类加载策略,以解决可能存在的类版本冲突问题。 WebSphere应用服务器默认的类加载顺序是先从系统类加载器(System ClassLoader)...

    java之jvm学习笔记五(实践写自己的类装载器)

    编写自定义类装载器时,你可能会遇到的问题包括类的加载顺序、类的可见性、类的唯一性以及如何处理加载失败的情况等。这些问题都需要在设计和实现时仔细考虑。 通过实践编写自己的类装载器,不仅可以加深对JVM内部...

    WAS+V7+理解类装入器-红皮书.pdf

    这些类装载器设计用于解决Java EE应用中常见的类冲突问题,提供灵活的配置选项,使开发者可以根据应用的具体需求来调整类的装载顺序和来源。 **WebSphere扩展类装载器** WebSphere扩展类装载器是一种特殊的类装载器...

    Java开发技术大全(500个源代码).

    loadClass.java 动态装载一个类 Shape.java 一个用于测试的简单类 useArray1.java 用反射机制使用数组示例1 useArray2.java 用反射机制使用数组示例2 第10章 示例描述:本章学习泛型。 demoBounds.java 演示有...

    Java类加载器加载类顺序

    sun提供了各个平台的JVM实现–也是说jvm不是跨平台的,编译好的字节码文件被放在不同的操作系统平台上的jvm所解释执行,这个章节主要解释一下JVM装载类的机制  1.ClassLoader是什么?  一个类如果要被JVM所调度...

    azxnet#thinking-in-java#6.9 初始化和类装载1

    装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。保证这个顺序是非常关键的,因为衍生类的初始化可

    quanke#think-in-java#6.9 初始化和类装载1

    装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。保证这个顺序是非常关键的,因为衍生类的初始化可

    面向实时JAVA工作平台的设计研究.pdf

    本论文设计了一个面向实时JAVA工作平台的类装载器,以期达到降低IPOR处理器的指令实现复杂度,提高IPOR处理器的效率。该平台的硬件或操作系统平台上安装了JAVA平台之后,JAVA应用程序就可以运行。JAVA应用程序可以在...

    java程序员考试题库

    执行类中的代码 > 装载类 > 校验类:不正确,执行顺序不对。 - B. 校验类 > 装载类 > 执行类中的代码:不正确,装载应该在前面。 - C. 装载类 > 执行类中的代码 > 校验类:不正确,校验应在装载之后立即进行。 -...

    Java 虚拟机概述.ppt

    类装载器按照“加载”、“连接”(验证、准备、解析)、“初始化”的顺序工作,确保类的正确性和安全性。 在JVM中,线程可以分为守护线程和非守护线程。守护线程(如垃圾收集器)不阻止JVM的退出,而非守护线程(如...

    贪心算法-最优装载

    在最优装载问题中,贪心策略是按照物体重量由小到大的顺序选择物体。原因是,如果我们先尝试装载较重的物体,可能会很快超过重量限制,而如果先装载较轻的物体,我们有可能在不超出限制的情况下装载更多的物体。因此...

    Java面试资料PDF(按章节顺序重新整理了一遍,顺序非视频中的顺序,但内容是全的)

    - 装载:加载类文件到内存。 - 链接:解析类信息,包括分配内存、设置默认值和符号引用转换。 - 初始化:执行静态初始化代码块和构造器。 6. **Java类加载器**: - BootstrapClassLoader:加载核心库。 - ...

    2021Java大厂面试题——大厂真题之携程-Java高级.pdf

    - **装载(Load)**:在这个阶段,类加载器负责查找并导入Class文件。这个过程涉及到从文件系统中读取二进制流(即.class文件),将其转化为JVM可以理解的格式。 - **连接(Linking)**:连接过程包括验证(Verification)...

    金蝶Apusic应用服务器V6参考b手册b.doc

    简言之,当Classloader链上的某一Classloader收到类装载请求时,会按顺序向上询问其所有父节点,直至最顶端(BootstrapClassLoader),任何一个节点成功受理了此请求,则返回,如果所有父节点都不能受理,这时候才由...

    Java中对象初始化顺序的详细介绍

    首先,Java类的加载过程分为三个阶段:装载、链接和初始化。装载是将类的.class文件读入内存,并为之创建一个Class对象。链接则是将类的二进制数据合并到JVM的运行时环境中,包括验证、准备和解析。初始化则是执行类...

Global site tag (gtag.js) - Google Analytics