jvm中类的加载、连接与初始化
直接看一个例程
??看上去很绕,可以走读一遍自己给出一个打印结果。。。。
?如我所愿了。。。。只是调换了一下代码顺序而已,这是为什么呢?而且为什么只有B会受影响,而A不会受影响呢?解释这个问题只是需要去了解jvm在“真正执行一个java类的main()”之前,做了哪些事情?简单的说,有三件事情
加载连接(其中又分解为验证、准备、解析三个步骤)初始化
也许有些书上也有类似的图,而且每个词听上去都很不具体。“加载什么”、“准备什么”。。。。这是这篇blog想搞清楚的核心问题,下面就各个击破,分别对每一步讲一些之前了解到的理解
加载它直接表现出来的代码应该是ClassLoader.getSystemClassLoader().loadClass("com.my.test.AbcClass")。所以具体完成类的加载工作的,是常被提到的类加载器ClassLoader,它就是专门干这件事的。“类的加载”具体而言就是指将类.class文件中的二进制数据读入到内存中将其放在方法区内,然后在堆区创建一个java.lang.Class对象,所以说“加载”的最终产出是堆中的一个Class对象,它一产生,加载这件事就干完了。这里又引出一个东东——方法区
-------------------------------------------分割线-------------------------------------------
说完以上这些,开篇的疑惑就可以解除了。。。【代码1】的执行顺序如下:?A) ?加载&连接类JvmClassTest,“连接”中的“准备”过程会为分别为三个static变量开辟对内存,并给默认值int A 开辟4字节,给默认值0int B 开辟4字节,给默认值0JvmClassTest OBJ 给默认值null
?B) 下面进入类的初始化阶段,按顺序做static动作static JvmClassTest OBJ = new JvmClassTest()调用了构造方法,故A++B++,此时A由0->1,B由0->1static int A这句无赋值动作,什么也不做static int B = 0,这句B由1->0最终,static代码块打印出了刚才看到的 A:1,B:0
?C) 初始化完成之后,开始执行main方法,B由0->-1。完毕,jvm进程终止。
而【代码2】中只是相当于将1.放到了3.之后,所以得到了不同的结果。
最后还有一个问题可以问一下自己,上面这个代码对应到“触发类初始化的6个场景”中,应该对上哪一条呢?“2.访问类或接口的statis变量,或者对statis变量赋值”,看上去是这个,是吗?通过代码还是可以验证的,只要在main()方法第一句加一个打印发现static块先执行了,而后才执行的System.out.println("test"),当时我看到这个结果之后,才恍然大悟,“6. Jvm启动时被标明为启动类的类”,Eclipse执行时将该类作为启动类拉,java命令一执行,当场就触发了JvmClassTest类的初始化,进而连带触发了加载&连接动作,而后执行JvmClassTest类的初始化,初始化完毕之后才开始步入main()方法体(此时此刻,static代码块已经在控制台打出了A、B的值了。。。),可能例程代码可以更纯粹一点。。。。。?终。 6 楼 ls8023 2012-02-21 受教了,不错 7 楼 iamzhongyong 2012-02-26 超哥的博客好给力啊呵呵,第一篇文章就有这么多人看呵呵。佩服