jvm-类加载

类加载
整个生命周期包括:加载--验证--准备--解析--初始化--使用--卸载
加载-验证-准备-初始化--卸载的开始顺序是一定的
解析是可能在初始化后


初始化:有切只有四种情况要对累进行初始化
1、使用new关键子实例化对象,调用接口的静态变量,给接口的静态变量赋值(被final修饰,或已在编译期把结果放入常量池的静态子段除外),调用一个类的静态方法
2、对类进行反射调用
3、初始化一个类其父类没有进行初始化,要先初始化其父类
4、虚拟机启动时,指定执行的主类


准备:
为变量分配内存,并设置变量的默认初始值。
注意:
1、这里的初始值并不是程序员赋的值,而是类型变量的0值。
2、分配内存仅包括类变量。
3、特殊情况:如果是final修饰的变量,将会赋给程序员给的初始值。

解析:虚拟机将常量池中的符号引用替换成直接引用的过程。
符号引用:以组符号来描述引用的目标,符号可以是任何形式的字面量。与虚拟机实现的内存布局无关,引用的目标可能不在内存中。
直接引用:是直接指向目标的指针、相对偏移量或个间接定位到目标的句柄,目标是已经在内存的。
解析动作主要针对类或接口、子段、类方法、接口方法四类符号引用。


初始化:为类中的变量赋值程
1、初始化时执行类构造器<clinit>()方法的过程
2、<clinit>()方法是由编译器自动收集类中的所有类变量的赋值和静态语句块中的语句合并产生的。
3、不需要显示调用父类构造器,虚拟机会保证子类<clinit>()方法执行之前父类的<clinit>()方法已经执行完毕。
4、父类中定义的静态语句块要优先于子类中定义的静态语句块。
5、<clinit>()方法不是必须的,一个类中没有类变量赋值或静态语句块,可以没有该方法。
6、接口中执行<clinit>()方法之前不需要执行父类的<clinit>()方法,只有调用到父类的变量时才需要。
7、<clinit>()方法在类中是加锁和同步的。

类与类的加载器
1、比较两个类是否相等,只有在这两个类时由同一个累加载器加载的前提下才有意义。
2、加载方式:启动类加载、扩展类加载、系统类加载
3、双亲委派机制保证了在java中的每个类都是唯一的。

运行时栈帧
1、每一个栈帧包括局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。
2、局部变量表:存储方法的参数和方法内部变量。
3、操作数栈:

编译器可知,运行期不可用:静态方法、私有方法、实例构造器和父类方法
非虚方法:在加载的时候就会把符号引用解析为该方法的直接引用。
非虚方法:静态方法、私有方法、实例构造器、父类方法和final修饰方法


静态类型:接口或抽象类变量
实际类型:实现类或子类变量
方法的重载:通过参数的数量和参数的类型来确定,参数是否相同是通过参数的静态类型是否相同来判定的。
调用重载方法时,如果找不到完全匹配的方法,会选择调用一个最合适的方法。


静态分派:所有依赖静态类型来定位方法执行版本的分派动作
典型应用:方法的重载

动态分派:运行期间根据实际类型确定方法执行版本的分派过程
典型应用:方法重写


多态查找过程:
1、找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C。
2、如果在类型C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,如果通过
则返回这个方法的直接引用,查找结束,不通过返回IllegalAccessError异常。
3、否则,按照继承关系从下往上依次对C的各个父类进行第2步
4、如果最终没找到,返回AbstractMethodError

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值