A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张校云 黑马帝   /  2011-10-12 11:44  /  2560 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 庞金梁 于 2011-10-12 13:19 编辑

Java虚拟机管理类和对象的生命周期;

(1)类的生命周期从类被加载,连接,初始化开始,到类被卸载结束;

(2)类处于生命周期时,它的二进制数据位于运行时方法区内,在堆区还有一个相应的描述类的Class类的对象;

(3)只有当类处于生命周期中时,Java程序才能够使用它。



1.Java虚拟机及程序的生命周期

(1)通过java命令运行一个Java程序时,启动一个Java虚拟机进程;

(2)Java虚拟机进程从启动到终止的过程,称为Java虚拟机生命周期;

(3)程序生命周期和Java虚拟机生命周期是一致的,因为Java虚拟机进程从创建起的任务就是执行Java程序。

2.类的加载,连接和初始化

a.Java程序要使用某个类时,Java虚拟机要确保这个类被加载,连接和运行,其中连接包括验证,准备和解析。

b.加载:查找并加载类的二进制数据;

c.连接

  c.1 验证:确保加载类的正确性;

  c.2 准备:为静态变量分配内存,并将其初始化为默认值;

  c.3 解析:将类中的符号引用转换为直接引用。

d初始化:

   给类的静态变量赋予正确的初始值

(1)加载(加载的最终目标是实现将编译后的class文件(class文件采用字节码,是JVM的机器语言)装入内存运行时数据区的方法区中,并在内存运行时数据区的堆区生成一个class对象,这个对象可以引用到方法区中的类定义)

     1.1 加载需要完成:

       1.1.1 将类的.class文件中的二进制数据读到内存中的运行时数据区的方法区;

       1.1.2 在堆区创建一个java.lang.Class对象(对象都放在堆区),用于封装类在方法区内的数据结构。

     1.2 加载的最终产品是位于运行时数据区堆区的java.lang.Class对象,Class对象封装了类在方法区的数据结构,并向Java程序提供访问类在方法区内的数据结构的接口

     1.3 类的加载由加载器完成

        1.3.1 Java虚拟机自带的加载器(如果Java虚拟机是一个C++程序,则这些加载器是这个C++程序的一部分)

                 包括启动类加载器,扩展类加载器和系统类加载器《后两个都是java.lang.Class类的实例》

        1.3.2 用户自定义的类加载器

                 java.lang.Class的子类的实例,用户可以通过它定制类的加载方式(用户自定义的类加载器使Java具有动态连接的特性,即Java无需在编译时确定需要的组件<类>,在运行时动态确定需要加载的类)

     类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载过程中遇到.class文件缺失,类加载器等到程序首次调用类的时候报错   

     Java中的类加载器采用父亲委托机制,使用加载器加载类是,首先看其父亲是否能够完成类的加载,如果可以,则由父亲完成类的加载,返回加载的类的java.lang.Class对象,注意,加载器之间的父子关系并不是java中普通的继承关系,而是一种包含关系,具有父子关系的类也许是不同的类型。

(2)连接

       在连接阶段对静态变量分配内存(静态变量是类作用域变量,仅在类加载时分配一次内存),并赋予默认值。

(3)初始化

       类的初始化过程是执行类的初始化语句,包括静态变量的声明语句,以及静态代码块,静态代码块的作用即是为静态变量赋初始化值。

评分

参与人数 1技术分 +2 黑马币 +8 收起 理由
wangfayin + 2 + 8 赞一个!

查看全部评分

回复 使用道具 举报
Java中类的生命周期是怎样的?求详解

4 个回复

倒序浏览
宁超 黑马帝 2011-10-12 11:48:21
藤椅
在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。
    类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的http://java.lang.Class对象。用来封装数据。 但是同一个类只会被类装载器装载以前
  链接就是把二进制数据组装为可以运行的状态。
  链接分为校验,准备,解析这3个阶段
  校验一般用来确认此二进制文件是否适合当前的JVM(版本),
  准备就是为静态成员分配内存空间,。并设置默认值
  解析指的是转换常量池中的代*作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)
  完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。
  当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

评分

参与人数 1技术分 +2 黑马币 +8 收起 理由
wangfayin + 2 + 8

查看全部评分

回复 使用道具 举报
有图有真相,自己看吧

QQ截图20111012134624.png (63.5 KB, 下载次数: 15)

有图有真相,自己看吧

有图有真相,自己看吧

评分

参与人数 1技术分 +3 收起 理由
wangfayin + 3 很给力!

查看全部评分

回复 使用道具 举报
java虚拟机通过装载、连接和初始化一个java类型,使该类型可以被一个正在运行的java程序所使用。
装载就是把二进制形式的java类型读入java虚拟机中;
连接就是把已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去,连接阶段分为3个子步骤--验证、准备、解析。
之后就时初始化。

java虚拟机实现必须在每个类或接口首次主动使用时初始化。


下面这六种情形符合主动使用的要求:
1 、当创建某个类的新实例时(或者通过在字节码中执行new指令;或者通过不明确的创建、反射、克隆或者反序列化)。
2、当调用某的类的静态方法时(即在字节码中执行invokestatic指令时)。
3、当使用某个类或接口的静态字段,或者对该字段赋值时(即在字节码中,执行getstatic或putstatic指令时),用final修饰的静态字段除外,它被初始化为一个编译时的常量表达式。
4、当调用api中的某些反射方法时,比如类class中的方法或者java.lang.reflect包中的类方法。
5、当初始化某个类的子类时,(某个类初始化时,要求它的超类已经被初始化了)
6、当虚拟机启动某个被表明为启动类的类(即含有main方法的那个类)

注意:
使用一个非常量的静态字段只有当类或者接口的确声明了这个字段的时候才是主动调用;
类中声明的字段可能会被子类引用;接口中声明的字段可能会被子接口或者实现了这个接口的类引用。对于子类、子接口和实现了接口的类来说,就是被动调用--使用它们并不会触发它们的初始化。

如果程序不在引用某类型,那么这个类型就无法再对未来的计算过程产生影响。类型变成不可触及的,而且可以被垃圾收集。

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马