Java虚拟机的加载、连接和初始化
2012-05-16 10:31
246 查看
Java虚拟机在类的加载、连接和初始化阶段都做了哪些工作?
答:(1)加载阶段:查找并加载类的二进制数据。
(2)连接阶段:包括验证、准备和解析类的二进制数据。
验证:确保被加载的类是正确的。
准备:为类的静态变量分配内存,并将其初始化为默认值。
解析:把类中的符号引用都替换成直接引用。
(3)初始化:给类的静态变量赋予正确的初始值。
在类或接口被加载和连接的时机上,Java虚拟机规范给实现提供了一定的灵活性,但是它严格定义了初始化的时机,就是所有Java虚拟机实现必须在每个类或者接口被Java程序“首次主动使用”时才初始化它们。
Java类在哪些情况下才会被初始化?
答:根据Java虚拟机规范,只有在程序首次主动使用一个类或者接口时才会初始化它。要说明Java类在哪些情况下会被初始化,就是要找出哪些活动被视作程序对类或接口的主动使用。主要6个活动会使得Java类被初始化:
(1)最基本的就是创建类的实例,这个肯定是要对类进行初始化的。创建类的实例的途径主要有:使用new语句创建实例,或者通过反射、克隆以及反序列化手段来创建实例。
(2)调用类的静态方法。
(3)访问某个类或者接口的静态变量,或者对该静态变量赋值。
(4)调用Java API中某些反射方法,比如调用Class.forName("xxx")方法,假定xxx类还没有被初始化,那么forName()方法就会初始化xxx类,然后返回代表这个类的Class实例。
(5)初始化一个类的子类。对子类的初始化可以看作对它父类的主动使用,因此会初始化它的父类。
(6)Java虚拟机启动时被标明为启动类的类。比如,我们使用Java xxx来执行程序,那么这个xxx被看作是启动类,Java虚拟机会首先初始化它。
除了以上6中情况,其他使用Java类的情况都会被看作类的被动使用,都不会导致类的初始化。
举一个例子说明一下Java虚拟机不对类进行初始化的情况:
[java] view
plaincopy
import java.lang.*;
class UnloadedClassTesting{
public static final int a=2*3;
static {
System.out.println("Class Loaded!!");
}
}
public class TestInit{
public static void main(String[] args){
System.out.println("a="+UnloadedClassTesting.a);
}
}
程序段打印的结果是:
Lab-Computer-0db2f6:JavaExercises labuser$ javac TestInit.java
Lab-Computer-0db2f6:JavaExercises labuser$ java TestInit
a=6
Lab-Computer-0db2f6:JavaExercises labuser$
显然没有对UnloadedClassTesting类进行初始化,UnloadedClassTesting类中的变量a是编译时常量,在编译阶段就已经计算初始化好了,当使用UnloadedClassTesting.a访问变量a的时候并没有导致类的初始化。
但是,如果上面的实例中的静态常量在编译阶段不能取得固定的值,那么程序对类的这种变量的使用,被看作时对类主动使用,会导致类的初始化。把上面的例子稍微改动一下:
[java] view
plaincopy
import java.lang.*;
import java.util.*;
class UnloadedClassTesting{
public static final int a=(int)(Math.random()*10)/10+1;
static {
System.out.println("Class Loaded!!");
}
}
public class TestInit{
public static void main(String[] args){
System.out.println("a="+UnloadedClassTesting.a);
}
}
<div class="Egm700">
</div>
程序运行的结果:
Lab-Computer-0db2f6:JavaExercises labuser$ javac TestInit.java
Lab-Computer-0db2f6:JavaExercises labuser$ java TestInit
Class Loaded!!
a=1
可以从结果中看出,类已经被加载和初始化了。
答:(1)加载阶段:查找并加载类的二进制数据。
(2)连接阶段:包括验证、准备和解析类的二进制数据。
验证:确保被加载的类是正确的。
准备:为类的静态变量分配内存,并将其初始化为默认值。
解析:把类中的符号引用都替换成直接引用。
(3)初始化:给类的静态变量赋予正确的初始值。
在类或接口被加载和连接的时机上,Java虚拟机规范给实现提供了一定的灵活性,但是它严格定义了初始化的时机,就是所有Java虚拟机实现必须在每个类或者接口被Java程序“首次主动使用”时才初始化它们。
Java类在哪些情况下才会被初始化?
答:根据Java虚拟机规范,只有在程序首次主动使用一个类或者接口时才会初始化它。要说明Java类在哪些情况下会被初始化,就是要找出哪些活动被视作程序对类或接口的主动使用。主要6个活动会使得Java类被初始化:
(1)最基本的就是创建类的实例,这个肯定是要对类进行初始化的。创建类的实例的途径主要有:使用new语句创建实例,或者通过反射、克隆以及反序列化手段来创建实例。
(2)调用类的静态方法。
(3)访问某个类或者接口的静态变量,或者对该静态变量赋值。
(4)调用Java API中某些反射方法,比如调用Class.forName("xxx")方法,假定xxx类还没有被初始化,那么forName()方法就会初始化xxx类,然后返回代表这个类的Class实例。
(5)初始化一个类的子类。对子类的初始化可以看作对它父类的主动使用,因此会初始化它的父类。
(6)Java虚拟机启动时被标明为启动类的类。比如,我们使用Java xxx来执行程序,那么这个xxx被看作是启动类,Java虚拟机会首先初始化它。
除了以上6中情况,其他使用Java类的情况都会被看作类的被动使用,都不会导致类的初始化。
举一个例子说明一下Java虚拟机不对类进行初始化的情况:
[java] view
plaincopy
import java.lang.*;
class UnloadedClassTesting{
public static final int a=2*3;
static {
System.out.println("Class Loaded!!");
}
}
public class TestInit{
public static void main(String[] args){
System.out.println("a="+UnloadedClassTesting.a);
}
}
程序段打印的结果是:
Lab-Computer-0db2f6:JavaExercises labuser$ javac TestInit.java
Lab-Computer-0db2f6:JavaExercises labuser$ java TestInit
a=6
Lab-Computer-0db2f6:JavaExercises labuser$
显然没有对UnloadedClassTesting类进行初始化,UnloadedClassTesting类中的变量a是编译时常量,在编译阶段就已经计算初始化好了,当使用UnloadedClassTesting.a访问变量a的时候并没有导致类的初始化。
但是,如果上面的实例中的静态常量在编译阶段不能取得固定的值,那么程序对类的这种变量的使用,被看作时对类主动使用,会导致类的初始化。把上面的例子稍微改动一下:
[java] view
plaincopy
import java.lang.*;
import java.util.*;
class UnloadedClassTesting{
public static final int a=(int)(Math.random()*10)/10+1;
static {
System.out.println("Class Loaded!!");
}
}
public class TestInit{
public static void main(String[] args){
System.out.println("a="+UnloadedClassTesting.a);
}
}
<div class="Egm700">
</div>
程序运行的结果:
Lab-Computer-0db2f6:JavaExercises labuser$ javac TestInit.java
Lab-Computer-0db2f6:JavaExercises labuser$ java TestInit
Class Loaded!!
a=1
可以从结果中看出,类已经被加载和初始化了。
相关文章推荐
- Java虚拟机的加载、连接和初始化
- [置顶]类的加载连接初始化
- 类的加载、连接和初始化 (转)
- svn 无法连接主机, 无法加载或初始化请求的服务提供程序
- jvm之类的加载、连接、初始化
- Java虚拟机类加载初始化解析
- java类的加载、连接和初始化
- 类的加载、连接与初始化过程的详细分析(上)
- 类加载机制与反射1——类的加载、连接和初始化
- Java中类的加载、连接和初始化
- java类加载、连接和初始化
- 【已解决】使用vncviwer 连接vncserver的时候报错:getnameinfo:无法加载或初始化请求的服务提供程序。(10106)
- 【JVM】类加载、连接和初始化过程
- Java虚拟机:加载、链接与初始化
- 类的加载、连接与初始化过程的详细分析(中)
- 类的加载,连接,初始化详解
- 类的加载、连接与初始化过程的详细分析(下)
- JAVA虚拟机(JVM)——类加载的时机之类的初始化
- JVM的类加载机制: 加载、连接、初始化。
- 类的加载连接初始化