Java代码运行机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java代码运行机制相关的知识,希望对你有一定的参考价值。

  Java代码编译后生成一种与平台无关的字节码(也就是class文件)。当然,这种字节码不是可执行的,必须使用Java解释器来解释执行。负责解释执行字节码文件的是Java虚拟机,即JVM。JVM是可运行Java字节码文件的虚拟计算机。所有平台上的JVM向编译器提供相同的编程接口,而编译器只需要面向虚拟机,生成虚拟机理解的代码,然后由虚拟机来解释执行。在一些虚拟机的实现中,还会将虚拟机代码转换成特定系统的机器码执行,从而提高执行效率。

  当我们调用Java命令运行某个java程序时,该命令将会启动一条Java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少个线程,它们都处于该Java虚拟机进程里。同一个JVM的所有线程、所有变量都处于同一个进程里,它们都使用该JVM进程的内存区。

  当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载、连接、初始化三个步骤来对该类进行初始化,如果没有意外,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化。

1.加载

类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说程序中使用任何类时,系统都会为之建立一个java.lang.Class对象(类,实际上也是对象,它们都是java.lang.Class的实例)。

类的加载由类加载器完成,类加载器通常由JVM提供,这些类加载器也是我们前面所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过集成ClassLoader基类来创建自己的类加载器。

类加载器通常无须等到”首次使用“该类时才加载该类,Java虚拟机规范允许系统预先加载某些类。

2.连接

当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段将会负责把类的二进制数据合并到JRE中。

类连接又可分为如下三个阶段:

(1)验证

检验被加载的类是否有正确的内部结构,并和其他类协调一致

(2)准备

为类的静态属性分配内存,并设置默认初始值

(3)解析

将类的二进制数据中的符号引用替换成直接引用

3.初始化

在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对静态属性进行初始化。

Java类中对静态属性指定初始值有两种方式:

1)声明静态属性时指定初始值;

2)使用静态初始化块为静态属性指定初始值。如果在这两种方式中都对同一静态属性指定初始值,JVM会按这些语句在程序中的排列顺序依次执行它们。

JVM初始化一个类包含如下几个步骤:

1)假如这个类还没有被加载和连接,程序先加载并连接该类。

2)假如该类的直接父类还没有被初始化,则先初始化其父类。

3)假如类中有初始化语句,则系统依次执行这些初始化语句。

类初始化的时机

Java程序首次通过下面6种方式来使用某个类或接口时,系统就会初始化该类或接口:

1)创建类的实例

2)调用某个类的静态方法

3)访问某个类或接口的静态属性,或为该静态属性赋值

4)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

5)初始化某个类的子类

6)直接使用java.exe命令来运行某个主类,当运行某个主类时,程序会先初始化该主类

除此之外,下面有几种情形需要特别指出:

对于一个final型的静态属性,如果该属性可以在编译时就得到属性值,则可认为该属性可被当成编译时常量。当程序使用编译时常量时,系统会认为这是对该类的被动使用,所以不会导致该类的初始化。

反之,如果final类型的静态属性的值不能在编译时得到,必须等到运行时才可以确定该属性的值,如果通过该类来访问该静态属性,则可以认为是主动访问使用该类,将会导致该类被初始化。

以上是关于Java代码运行机制的主要内容,如果未能解决你的问题,请参考以下文章

java IONIOAIO详解

java反射机制

Java基础Java反射机制浅解

Java自学笔记第二十天

Java中的反射该如何使用?

Java反射