02月28, 2018

虚拟机类加载过程-初始化

流程

  

  • graph LR
  • 加载-->验证
  • 验证-->准备
  • 准备-->解析
  • 解析-->初始化
  • 初始化-->使用
  • 使用-->卸载
ada

初始化

  java虚拟机规范,所有java虚拟机实现必须在每个类或接口被java程序首次主动使用时才初始化。
主动使用的几种情况:

  • 创建类的实例
  • 访问某个类或者接口的静态变量,或者对该静态变量赋值(如果访问静态编译时常量(即编译时可以确定值的常量)不会导致类的初始化)
  • 调用类的静态方法
  • 反射(Class.forName(xxx.xxx.xxx))
  • 初始化一个类的子类(相当于对父类的主动使用)
  • Java虚拟机被标明为启动类的类(包含main方法的)

  看下面的实例

  • package chapter7.classload.initialization;
  • public class TestClass {
  • private String name;
  • public static final int price=10;
  • static {
  • System.out.println("Initializing");
  • }
  • TestClass() {
  • System.out.println("Building");
  • }
  • TestClass(String name) {
  • this.setName(name);
  • }
  • public static String playToy(String player) {
  • String msg = player + " plays " ;
  • System.out.println(msg);
  • return msg;
  • }
  • public void setName(String name) {
  • this.name = name;
  • }
  • }
processing

测试类:

  • package chapter7.classload.initialization;
  • public class RunTest1 {
  • public static void main(String[] args) throws ClassNotFoundException {
  • // 对上面的类,执行下面的代码:
  • Class<?> c = Class.forName("chapter7.classload.initialization.TestClass");
  • // c.newInstance();
  • }
  • }
aspectj

输出:

  • Initializing

问题
  初始化时仅会初始静态代码块(static{}块中)的语句所有类变量的赋值动作,以下面代码为例,输出结果B的值为2

  • static class Parent {
  • public staic int A = 1;
  • static {
  • A = 2;
  • }
  • }
  • static class Sub extends Parent {
  • public static int B = A;
  • }
  • public static void main(String[] args) {
  • System.out.println(Sub.B);
  • }
java

分析
   Parent是Sub的父类,查看本文开头的规范初始化一个类的子类(相当于对父类的主动使用),所以会初始化Parent类,但初始化时仅会初始化静态代码和类变量赋值,所以,会执行static { A = 2; }, 所以B = 2了

本文链接:https://www.daguanren.cc/post/java_vm_classload_initialization.html

-- EOF --

Comments