Java---类的生命周期和加载机制

     类的生命周期:(七步)
            1、加载:查找并加载类的二进制数据。
                (1)通过“类全名”来获取定义此类的二进制字节流
                (2)将字节流所代表的静态存储结构转换为方法区的运行时数据结构
                (3)在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口

            链接:
             2、 验证:确保被加载类的正确性。
                    验证是链接阶段的第一步,这一步主要目的是确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。
                    验证阶段主要包含如下四个检验过程:
                         (1)文件格式验证:验证class文件格式规范。
                        (2)元数据验证:这个阶段是对字节码描述的信息进行语义分析,以保证描述的信息符合java语言规范要求。
                        (3)字节验证码:进行数据流和控制流分析,这个阶段对类的方法体进行校验分析,这个阶段的任务是保证被校验类的方法在运行时不会做出危害虚拟机安全的行为。
                        (4)符号引用验证:符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用类中的类,字段和方法的访问性(private、protected、public、default)是否可被当前类访问。

             3、准备:为类的静态变量分配内存,并将其初始化为默认值
                     准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。      
                      注意两点:
                        这时候进行内存分配的仅包括类变量(static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。
                        这里所说的初始值“通常情况”下是数据类型的零值。
                        比如:public static int value = 12;那么变量value在准备阶段过后的初始值为0而不是12,因为这时候尚未开始执行任何java方法,而把value赋值为12的动作将在初始化阶段才会被执行。

               4、 解析:把类中的符号引用转换为直接引用。
                     解析阶段是虚拟机常量池内的符号引用替换为直接引用的过程。
                     符号引用:
                         是一组符号来描述所引用的目标对象,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标对象并不一定已经加载到内存中。
                     直接引用:
                         直接引用可以是直接指向目标对象的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机内存布局实现相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同,如果有了直接引用,那引用的目标必定已经在内存中存在。

                5、初始化:为类的静态变量赋予正确的初始值。
                      类的初始化阶段是类加载过程的最后一步,在准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,
                      则是根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。

                     在以下四种情况下初始化过程会被触发执行:
                        (1)遇到new、getstatic、putstatic或invokestatic这四个字节码指令时,如果类没有进行过初始化,则需先触发其初始化。
                        (2)使用java.lang.reflect包的方法对类进行反射调用的时候。
                        (3)当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先触发其父类的初始化。
                        (4)jvm启动时,用户指定一个执行的主类(包含main方法的那个类),虚拟机会先初始化这个类。
                6、使用
                              在类的使用过程中依然存在三步:对象实例化、垃圾收集、对象终结
                            (1)对象实例化:
                                         就是执行类中构造函数的内容,如果该类存在父类JVM会通过显示或者隐示的方式先执行父类的构造函数,在堆内存中为父类的实例变量开辟空间,并赋予默认的初始值,然后在根据构造函数的代码内容将真正的值赋予实例变量本身,然后,引用变量获取对象的首地址,通过操作对象来调用实例变量和方法 
                            (2)垃圾收集:
                                          当对象不再被引用的时候,就会被虚拟机标上特别的垃圾记号,在堆中等待GC回收 
                           (3)对象的终结:
                                        对象被GC回收后,对象就不再存在,对象的生命也就走到了尽头
                7、卸载
                             即类的生命周期走到了最后一步,程序中不再有该类的引用,该类也就会被JVM执行垃圾回收,从此生命结束…
                     其中加载、链接(验证、准备、解析)、初始化为类的加载过程(前五步)。

        类加载器:
            分类:
               (1)启动类加载器(Bootstrap ClassLoader):负责加载JAVA_HOME\lib目录中并且能被虚拟机识别的类库到JVM内存中,如果名称不符合的类库即使放在lib目录中也不会被加载。该类加载器无法被Java程序直接引用。

               (2)扩展类加载器(Extension ClassLoader):该加载器主要是负责加载JAVA_HOME\lib\,该加载器都可以被开发者直接使用。

               (3)应用程序类加载器(Application ClassLoader):该类加载器也成为系统类加载器,它负责加载用户类路径(Classpath)上所指定的类库,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

                对于上面三种类加载器,其中启动类加载器(Bootstrap ClassLoader)使用C++语言实现,属于虚拟机自身的一部分,不是ClassLoader的子类。所有其他的类加载器,这些类加载器是由Java语言实现,独立于JVM外部,并且全部继承自抽象类lava.lang.ClassLoader。

            双亲委派:
                如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值