上篇文章已经说了类型生命周期中的装载及连接过程,下面将主要描述下初始化过程。
首先要搞清楚初始化和实例化之间的区别:实例化是根据指定类型,在堆中生成一个实例对象,而初始化则不是,它所作的处理主要是为类变量赋予初始值,这里所说的初始值是相对于连接准备阶段的默认值而言的。
注意类变量和对象变量的区别:类变量是指类的静态变量或静态块,初始化时会重新赋值,而对象变量是实例化一个对象后,该对象特有的变量值(这是我的理解。实例如下:
运行如下代码:
public class Test1 {
public int noStaticNum = printStaticNum();
public static int staticNum = printStaticNum();
static {
System.out.println("执行静态块!");
}
public static int printStaticNum() {
System.out.println("execute printStaticNum() method !");
return 1;
}
public int printNoStaticNum() {
System.out.println("execute printNoStaticNum() method !");
return 1;
}
public static void main(String[] args) {
}
}
得出结果:execute printStaticNum() method !
执行静态块!
从执行结果中得知,初始化时,staticNum和静态块会重新赋值,而noStaticNum则不会。
初始化必须发生在装载、连接以后,java虚拟机一般会在每个类或接口主动使用时才会对类型进行初始化。下面六中情形符合主动使用的要求:
1.当创建某个类的新实例时。注:包括创建的所有方式,如new、反射、克隆以及反序列化等
2.当调用某个类的静态方法时
3.当使用某个类或接口的静态字段,或对该静态非常量字段进行赋值时。注意:用final修饰的静态字段除外,因为在编译阶段时,它就被替换成一个常量表达式
4.调用java API中的某些反射方法时,比如类Class中的方法或java.lang.reflect包中的方法
5.初始化某个类的子类时(某个类初始化时,要求它的超类已经被初始化了)
6.虚拟机启动时,包含有main方法的类
补充: 创建类的新实例的方式主要有四种:
1.明确使用new操作符
2.调用Class或Constructor对象的newInstance()方法
3.调用现有对象的clone()方法
4.通过java.io.ObjectInputStream类的getObject()方法反序列化
当使用某个类或接口的静态字段,或对该静态字段进行赋值时。注意:用final修饰的静态字段除外,因为在编译阶段时,它就被替换成一个常量表达式,不会作为类变量被保存到方法区中(具体可以写个类,编译成class文件,然后反编译即可看见结果)。具体分析见后面实例。
初始化某个类的子类时(某个类初始化时,要求它的超类已经被初始化了)。注意:该规则对应接口并不使用,只有在父接口所声明的非常量静态字段被使用时,它才会被初始化,而不是因为它的子类或子接口的初始化而被初始化。注意:虽然不会被初始化,但是会被装载。示例说明:
/**
* Dog的超类是个父类,而不是接口
*/
public class Animal {
static String id = "Animal"; //类变量 ,注意不是对象变量
static String s2 = Test.print();
}
/**
* 子类,超类是Animal类
*
*/
public class Dog extends Animal{
static String dogId = "Dog"; //类变量
static {
System.out.println("Dog initialized !");
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
String s = Dog.id; //------------1
//String s = Dog.dogId; //-------------2
System.out.println(s);
}
public static String print() {
System.out.println("execute Animal's print() method");
return "void";
}
static {
System.out.println("Test initialized !");
}
}
运行,得出测试结果如下:
1. 当注掉代码1,使用代码2时,打印结果信息:
Test initialized !
execute Animal's print() method
Dog initialized !
Dog
2. 当注调代码2,使用代码1时,打印结果信息:
Test initialized !
execute Animal's print() method
Animal
分析:从测试结果1可以看出,当超类是类时,子类初始化时,父类也初始化,并且在子类之前初始化。
实例二:
/**
* Dog的超类是个接口,而不是类
*/
public interface Animal {
static String id = "Animal"; //接口中的局部类型,默认为static final
static String s2 = Test.print();
}
/**
* 子类,超类是Animal接口
*
*/
public class Dog implements Animal{
static String dogId = "Dog"; //类变量
static {
System.out.println("Dog initialized !");
}
}
测
试类Test.java内容不变,注掉代码段1,执行结果如下:
Test initialized !
Dog initialized !
Dog
从测试结果看可以看出,Dog类初始化前,它的接口Animal并没有初始化,从而得出,超类是接口时,子类初始化时,超类并不一定会被初始化
实例三:
/**
* Dog的超类是个接口,而不是类
*/
public class Animal {
final static String id = "Animal"; //当类变量是static final
final static String s2 = Test.print();
}
测试类Test.java不变,注掉代码段2,执行结果如下:
Test initialized !
Animal
分析: 当局部字段为静态常量类型时,使用该字段时,是不对该类进行初始化的。
卸载类型
JVM中类的生命周期和对象生命周期很相似。JVM创建并初始化对象,使程序能够使用创建好的对象。但是,但对象不再被使用时,则被JVM进行垃圾收集。类型也一样,但不在被使用时,也可被收集。
在类型生命周期过程中,类型被分为可触及的和不可触及的。可触及的类型还不可以被卸载收集,而不可触及的类则可以被卸载收集。
使用启动类装载器装载的类型永远是不可触及的,所以它们永远不会被卸载。一般可触及的类型都是被用户自定义装载器装载的,并且当前还在被使用的类型。
为什么要卸载并收集类型呢?上面描述过,类被装载后被存储到方法区,需占用一定的内存空间,如果不对用户自定义装载器装载的类进行收集,那么这样的类型将越来越多,最终会导致内存溢出等异常
分享到:
相关推荐
JVM——总结思维导图
关于JVM中对象的生命周期的讲解,不错!!
深入JVM内核—原理、诊断与优化视频教程 深入JVM内核—原理、诊断与优化视频教程
深入jvm 内核-原理,诊断于优化视频教程.算是比较基础的
深入JVM内核—原理、诊断与优化视频教程 深入JVM内核—原理、诊断与优化视频教程
深入JVM内核—原理、诊断与优化视频教程———目前,Java是更为流行的编程语言之一,它的基础平台就是JVM。除了Java,如JRuby、Scala、Clojure等语言也运.
主要介绍了Java对象在JVM中的生命周期详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
深入解析jvm深入解析jvm深入解析jvm深入解析jvm深入解析jvm深入解析jvm
1、java虚拟机的基本介绍。 2、字节码的执行 3、常用的jvm参数配置 4、算法和种类 5、gc参数配置 6、类加载器 7、性能监控工具 8、jvm堆栈分析
本书讲述了Java虚拟机一运行 所有Java程序的抽象计算机,还讲了几种与虚拟机密切相关的核心Java API。本书通过分析讲解、可运行的示例、参考资料和applet (它作为文中所述概念的交互式例示),提供了Java技术的深人...
JVM 深入JVM JVM详解 JVM知识点 java虚拟机 深入java虚拟机
JVM 完整深入解析.pdf
Inside Java Virtual Machine 中文版pdg版本 想深入了解JVM的必备书籍,欢迎下载 想深入了解JVM的必备书籍,欢迎下载 想深入了解JVM的必备书籍,欢迎下载 想深入了解JVM的必备书籍,欢迎下载
每个使用Java的开发者都知道Java字节码是在JRE中运行,而JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你...
JVM ——word文档总结下载地址-附件资源
1.13 慢慢琢磨JVM——恭喜JavaEye重新开张 2. 线程安全 2.1 java线程安全总结 3. JVM实战 3.1 通过Java/JMX得到full GC次数? 3.2 如何更快的启动eclipse 4. JVM基础 4.1 JVM内存管理:深入Java内存区域与OOM 4.2 ...
深入JVM整理文档
深入JVM内核—原理、诊断与优化视频教程
JVM=类加载器classloader+执行引擎executionengine+运行时数据区域runtimedataarea首先Java源代码文件被Java编译器编译为字节码文件,然后JVM中的类加载器加载完毕之后,交由JVM执行引擎执行。在整个