JVM(二)对象以及类加载

对象的创建:

Java程序在运行的过程中无时无刻的在创造着对象(new),在语言中仅仅是一个new关键字,而在虚拟机层面则是一个复杂的过程。

虚拟机遇到new字,首先检查一下线程池中能否找到这个类的符号引用,并检查这个符号所代表的类是否被已加载,解析和初始化,如果没有的话,就需要进行类加载

类加载之后虚拟机将进行内存分配,对象所需的内存时在类加载后就可以完全确定,分配方式:连续内存中用“指针碰撞的方法”,不连续的用“空闲列表的方式”,然后对所分配的的内存空间初始化为0值,
接着对对象进行必要的设置(这个对象是哪个类的实例,对象的哈希码,对象的GC分代)此时在虚拟机看来已经完成了对象的创建,但在Java程序看来才刚刚开始--------方法还没有执行,所有的字段都是0,然后按照程序员的意愿进行初始化。

类加载机制

在Class文件中描述的信息都需要加载到虚拟机中才能运行和使用的。虚拟机把描述类的信息加载到内存中,并对,数据进行校验,准备,解析,初始化,最终形成可以被虚拟机直接使用的Java类

类加载的时机
1,遇到new,getstatic,putstatic,以及调用静态方法,如果类没有初始化就要进行初始化
2,使用Java.lang.reflect包对类进行反射调用的时候
3,初始化一个类时
4,当虚拟机启动时,用户要指定一个要执行的主类

类加载的全过程
加载阶段:1,通过一个类的全限定名来获取定义这个类的二进制字节流 2,将字节流代表的静态储存结构转化为方法区的运行时数据结构。3,在内存中生成一个代表这个类的Java.long.Class对象,作为方法区这个类的各种数据访问的入口

验证阶段:Class文件中的字节流所包含的信息符合虚拟机的要求,并且不会对虚拟机造成伤害
包括:文件格式验证,元数据验证,字节码验证,符号引用验证

准备阶段:正式为类变量分配内存空间,并设置初始值的阶段,这些变量所用的内存空间都是在方法区中分配,这时候进行内存分配的是类变量,(不是实例变量)实例变量实例化是在对象实例化时随对象一起分到Java堆中的。初始值在通常情况下是数据类型的0值,此时的还没有执行任何Java方法,在赋值的指令被编译后,存放在类构造器中,赋值的的动作在初始化阶段才会执行

解析阶段:是将常量池中的符号引用变为直接引用,解析动作主要针对类或是接口,字段,类方法,接口方法,方法类型,方法句柄,和调用点限定符7类符号引用进行

初始化阶段:是类加载的最后一步,前面的过程中除了在加载阶段可以使用自定义的类加载器参与外,其他的动作都是完全由虚拟机主导控制的,到了初始化阶段才可以执行类中定义的Java程序代码
初始化阶段是执行类加载器的过程,程序员可以通过程序制定的主观计划去初始化类变量和其他资源。

** 方法 clinit()介绍**

clinit ()方法是编译器自动收集类的赋值动作语句和静态代码块语句合并而成的。收集顺序是由语句在源文件中出现的顺序决定的

这个方法也不是必须的,如果类和接口中没有静态代码块和赋值操作,编译器可以不用给这个类生成类加载器方法

接口的clinit方法和类的clinit方法的不同在于:不需要先执行父接口中的clinit方法,只有当父接口中定义的变量执行的时候,父接口才会初始化。接口的实现类在进行初始化的时候也不会执行此方法

虚拟机会保证一个类的clinit方法在多线程的环境下被正确的加锁,同步,一个类型只会被初始化一次。

类加载器
把通过一个类的全限定名来获取描述 这个类的二进制字节流的动作放到虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。
类加载器的作用:1,在类加载阶段 发生作用
2,比较两个类相等在同一个类加载器下才有意义,两个类即使是来自于同一个文件,被同一个虚拟机加载,只要加载他们的类加载器不是同一个的话,就不是同一个类

双亲委派机制

从Java虚拟机本身的角度来看,只有两种不同的类加载器,一种是启动类加载器(用C++实现),另一种是其他类加载器(Java语言写的)全部继承抽象类Java.long.ClassLoader

启动类加载器:这个类加载器将JAVA_HOME中bin目录下的类库加载到虚拟机内存中,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那么直接使用null替代即可。
它是ClassLoader中getSystemClassLoader()方法的返回值,一般称为系统类加载器,用于加载用户路径上指定的类库

由用户自定义类加载器往上到应用程序类加载器,再到扩展类加载器,最后到启动类加载器,这种加载器之间的关系被称为双亲委派模型,除了启动类加载器外,其他的类加载器都应该有自己的父类加载器,这里的父子关系不是通过继承实现的。而是通过使用组合关系,来复用父类加载器中的代码

过程:如果一个类加载器收到类加载的请求时,它不会用自身来进行加载,而是传给它的父类加载器,一直一直传给最顶层的启动类加载执行,如果父类加载器无法完成这个请求的话,就由子类加载器执行。

好处:Java类随着他的类加载器带有某种优先级的层次关系,对于保证程序的稳定性有很重要的作用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值