java类初始化器_Java类的加载和初始化

为什么说Java是跨平台语言

Java语言的运行环境是在Java虚拟机中。 Java虚拟机消除了各个平台之间的差异,只要操作系统平台下安装了Java虚拟机,那么使用Java开发的东西都能在其上面运行。如下图所示:

AAffA0nNPuCLAAAAAElFTkSuQmCC

Java虚拟机对各个平台而言,实质上是一个可执行程序。例如在windows平台下,java虚拟机就是一个java.exe进程而已。

JVM虚拟机启动和加载类过程

下面以一个简单的java程序,分析虚拟机启动过程。public class HelloWorld {    public static void main(String[] args) {

System.out.println("hello world");

}

}

当我们运行上面程序时,将会启动一个虚拟机进程,不管Java程序有多么复杂,启动了多少线程,它们都将处于该Java虚拟机进程里。具体过程如下:

1、根据JVM的内存配置,为JVM申请特定大小的内存空间

AAffA0nNPuCLAAAAAElFTkSuQmCC

2、创建一个引导类加载器实例

JVM申请好内存空间后,JVM会创建一个引导类加载器(Bootstrap Classloader)实例,引导类加载器是使用C++实现的,负责加载JVM虚拟机运行时所需的基本系统级别的类,如java.lang.String, java.lang.Object等。引导类加载器(Bootstrap Classloader)会读取 {JRE_HOME}/lib 下的jar包和配置,然后将这些系统类加载到方法区内。

方法区用于存储已经被虚拟机加载过的类信息、常量、静态变量、即时编译器编译出的代码等数据。

AAffA0nNPuCLAAAAAElFTkSuQmCCClass是一个实实在在的类,在包 java.lang 下。它跟我们自己定义的类一样,是一个实实在在的类,Class对象就是这个Class类的实例了。在Java里,所有的类的根源都是Object类,Class也不例外,它是继承自Object的一个特殊的类,它内部可以记录类的成员、接口等信息。

3、创建JVM 启动器实例 Launcher,并取得类加载器ClassLoader

上述步骤完成,JVM基本运行环境就准备就绪了。此时,JVM虚拟机会调用已经加载在方法区的类sun.misc.Launcher 的静态方法getLauncher(), 获取sun.misc.Launcher 实例:sun.misc.Launcher launcher = sun.misc.Launcher.getLauncher(); //获取Java启动器ClassLoader classLoader = launcher.getClassLoader();          //获取类加载器ClassLoader用来加载class到内存来

sun.misc.Launcher 使用了单例模式设计,保证一个JVM虚拟机内只有一个sun.misc.Launcher实例。在Launcher的内部,其定义了两个类加载器(ClassLoader),分别是sun.misc.Launcher.ExtClassLoader和sun.misc.Launcher.AppClassLoader,这两个类加载器分别被称为拓展类加载器(Extension ClassLoader) 和 应用类加载器(Application ClassLoader).如下图所示:

AAffA0nNPuCLAAAAAElFTkSuQmCC

此时的  launcher.getClassLoader() 方法将会返回 AppClassLoader实例。

当AppClassLoader加载类时,会首先尝试让父加载器ExtClassLoader进行加载,如果父加载器ExtClassLoader加载成功,则AppClassLoader直接返回父加载器ExtClassLoader加载的结果;

如果父加载器ExtClassLoader加载失败,AppClassLoader则会判断该类是否是引导的系统类(即是否是通过Bootstrap类加载器加载,这会调用Native方法进行查找);

若要加载的类不是系统引导类,那么ClassLoader将会尝试自己加载,加载失败将会抛出“ClassNotFoundException”。上面讨论的应用类加载器AppClassLoader的加载类的模式就是我们常说的双亲委派模型(parent-delegation model).

对于某个特定的类加载器而言,应该为其指定一个父类加载器,当用其进行加载类的时候:委托父类加载器帮忙加载;

父类加载器加载不了,则查询引导类加载器有没有加载过该类;

如果引导类加载器没有加载过该类,则当前的类加载器应该自己加载该类;

若加载成功,返回 对应的Class 对象;若失败,抛出异常“ClassNotFoundException”。

4、使用类加载器ClassLoader加载HelloWorld类

通过 launcher.getClassLoader()方法返回AppClassLoader实例,接着就是AppClassLoader加载HelloWorld类的时候了。

5、加载完成时候JVM会执行HelloWorld类的main方法入口

6、java程序运行结束,JVM销毁

类的初始化

在Java类中对类变量指定初始值有两种方式,一是声明类变量时指定初始值;二是使用静态初始化块为类变量指定初始值。

JVM会按照这些语句在程序中的排列顺序依次执行它们。另外,如果类的父类还没初始化,会先初始化父类。例如下面的类:public class Test {    static {

b = 6;

System.out.println("---------");

}    static int a = 5;    static int b = 9;    static int c;    public static void main(String[] args) {

System.out.println(Test.b);//结果为9

}

}

作者:匠丶

链接:https://www.jianshu.com/p/2000f9d805ef

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值