标签:
JVM简介
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
JVM类的加载
Java虚拟机的加载,连接,初始化。
Java程序对类的使用方式,分成两种,一是主动使用,二是被动使用,所有的Java虚拟机实现必须在每个类或者接口被Java程序程序“首次主动使用”时才初始化类。
主动使用包括六种:
-创建类的实例
-访问某个类或接口的静态变量,或者对该静态变量赋值
-调用类的静态方法
-反射(如 Class.forName(“com.tgb.java”))
-初始化一个类的子类
-Java虚拟机启动时被表明为启动类的类
类的加载,也许很熟悉了,在开始学习谭浩强的C语言的时候,就知道将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。
类的加载方式:
-从本地系统中直接加载
-通过网络下载.class文件
-从zip,jar等归档文件中加载.class文件
-从专有数据库中提取.class文件
-将Java源文件动态编译为.class文件
关于类的主动使用
类的解析阶段:
在解析阶段java虚拟机会把类的二进制中的符号引用替换成直接引用。
类的初始化阶段
当java虚拟机初始化一个类时,要求它的所有的父类都已经被初始化了,但是这条规则不适用接口
初始化一个类 并不会初始化它所实现的接口
初始化一个接口时,并不会先初始化它的父接口
对子类主动使用会导致父类初始化
对父类主动使用不会导致子类初始化
只有当程序访问的静态变量或者静态方法确实在当前类或者当前接口定义时,才可以认为是对类或者接口的主动使用。
调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化
上面的几点,只有在程序中才能真正的体现出来。
<pre name="code" class="java">package com.tgb.classLoader; public class TestSix { static { System.out.println("Test static block"); } public static void main(String[] args) { System.out.println(child3.a); child3.doSomethind(); } } class Parent3 { static int a = 3; static { System.out.println("Parent3 static block"); } static void doSomethind() { System.out.println("do something"); } } class child3 extends Parent3 { static { System.out.println("Child3 static block"); } }
Test static block
Parent3 static block
3
do something
上面是输出顺序,可能最大的疑惑就是在child3.a这段代码了,当调用a这个静态变量时,大家可能以为对child3的主动使用了,其实错了,只有当静态类或者变量存在child3时,才可以是对其的主动使用,但是静态变量a存在父类parent中,所以是对parent的主动使用了。输出parent3 static block就不足为奇了。
基础的一些概念在学习的时候可能不太注意但是如果真的在使用过程中,出现一些我们无法解释的现象时,回头看看基础的概念,问题就在其中
标签:
原文地址:http://blog.csdn.net/u010158267/article/details/51336093