码迷,mamicode.com
首页 > 其他好文 > 详细

运行机制和JVM

时间:2017-01-16 19:53:37      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:jre   str   开发者   不能   都对   其他   创建   机器码   时机   

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中。类连接又可分为如下三个阶段:

    • 验证:检验被加载的类是否有正确的内部结构,并和其他类协调一致
    • 准备:为类的静态属性分配内存,并设置默认初始值
    • 解析:将类的二进制数据中的符号引用替换成直接引用
  3. 初始化

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

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

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

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

    • 假如这个类还没有被加载和连接,程序先加载并连接该类。
    • 假如该类的直接父类还没有被初始化,则先初始化其父类。
    • 假如类中有初始化语句,则系统依次执行这些初始化语句。

类初始化的时机

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

  • 创建类的实例
  • 调用某个类的静态方法
  • 访问某个类或接口的静态属性,或为该静态属性赋值
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类,当运行某个主类时,程序会先初始化该主类

除此之外,下面有几种情形需要特别指出: 
对于一个final型的静态属性,如果该属性可以在编译时就得到属性值,则可认为该属性可被当成编译时常量。当程序使用编译时常量时,系统会认为这是对该类的被动使用,所以不会导致该类的初始化。 
反之,如果final类型的静态属性的值不能在编译时得到,必须等到运行时才可以确定该属性的值,如果通过该类来访问该静态属性,则可以认为是主动访问使用该类,将会导致该类被初始化。

运行机制和JVM

标签:jre   str   开发者   不能   都对   其他   创建   机器码   时机   

原文地址:http://www.cnblogs.com/studyhs/p/6290551.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!