java类的生命周期
运行时常量池,类加载器的作用,多态的原理,类的加密和解密
加载
1,类加载器根据类的全限名 通过不同渠道 以二进制流的方法获取字节码信息
2,加载完后,jvm会将字节码信息保存到方法区里
3,jvm在方法区里会生成一个instanceKlass对象,保存类的所有信息(基本信息,常量池,字段,方法,虚方法表(实现多态的基础))
4,还会在堆里生成一份与方法区中数据类似的java.lang.class对象,作用是在java代码中获取类的信息。方法区和堆里的信息相互关联。jdk8以后静态字段数据存储在栈里。
为什么在内存和栈里都要创建一个对象保存类的数据??
instanceKlass是C++编写的,java不能直接操作,但是java.lang.class是java封装后的对象,代码好获取。java.lang.class剔除了instanceKlass中的一些信息,剔除了一些开发不用的信息。
类加载器
类加载器是一个负责加载类的对象,用于实现类加载过程中的加载这一步。
每个 Java 类都有一个引用指向加载它的 ClassLoader。
数组类不是通过 ClassLoader 创建的(数组类没有对应的二进制字节流),是由 JVM 直接生成的
链接
1,验证
校验字节码信息是否满足《java虚拟机规范》,不满足就滚。程序员不用参与
常见校验内容
- 文件格式验证(Class 文件格式检查,校验文件开头)
- 元数据验证(字节码语义检查,比如:类一定有父类)
- 字节码验证(程序执行指令语义检查,比如:跳转的地方不能为空)
- 符号引用验证(比如是否引用了其他类的private方法)
2,准备
给静态(static)变量赋初始值
为什么一开始有初始值??
因为怕原来的地址上有残留值
编译器认为你后面不会变了,就直接给赋值了
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段
3,解析
解析阶段主要是将常量池中的符号引用替换为直接引用。虚拟机将常量池内的符号引用替换为指向内存的直接引用的过程。
符号引用就是在字节码文件中使用编号来访问常量池中的内容
符号引用:比如说#5
初始化
与程序员有关的阶段。给静态(static)变量赋最终值
执行静态代码块中的代码,并为静态变量赋值
从字节码角度分析就是执行了字节码文件中的clinit部分的字节码指令
当一个类编译为字节码文件,字节码文件的方法信息包括:init(构造方法),main方法,clinit(初始化阶段执行)。clinit方法中的执行顺序与java编写的顺序一致
类继承的情况:
数组的创建不会导致数组中元素的类进行初始化
final修饰的变量如果赋值的内容需要执行指令才能得到结果,会执行clinit方法进行初始化