反射
1:java开发工具可以帮助我们将代码编译为class字节码
2:类加载器加载class字节码,将字节码里面的指令放到内存执行,并且将数据动态分配到jvm内存呢模型中,
3:jvm'的分区
类的加载流程:
1:雷电加载指定就是将class文件找中的二进制数据读取到内存中。类、方法、常量、静态内容放到方法区。
2:但是要在堆中创建一个class对象,用开封装存储在方法区的数据结构
3:类的加载最终结果就是在对中产生了一个class对象,当前对象提供了访问方法区内容的接口
类加载器加载class文件,加载class文件有哪些方式:
1:直接从本地系统读取,直接加载
2:通过网络路径下载
3:zip,jar包读取文档中的class文件
4,从某些数据库中获取class文件
5:将java原文件动态编译成class文件
类的生命周期
类的加载过程:
加载、验证、准备、解析、初始化
加载:查找并加载类的二进制的数据
1:通过全限定名获取定义的而进制数据
2:将字节流所代表的静态储存内容放入方法区
3:在java堆中生成一个代表当前对象的java.lang.Class对象,作为方法区的访问接口,整个类的生命周期中,最容易控制的就是当前阶段,你可以自己定义类加载器来加载数据
验证:验证的主要目的是确保被加载类的正确性
验证主要内容是验证你的class文件的信息中是否符合java虚拟机加载的要求,并且你的信息不会危害java虚拟机的安全
1:文件格式的验证:看看是否常量池中数据是否有必备支持的类型
2:元数据的验证:保证类所描述的信息是符合java的规范,当前这个类是否有除了java.lang.Object之外的父类
3:字节码的校验:校验语法正确性,是否符合逻辑。
4:符号应用校验:确保解析动作能正确运行
效验阶段是非常重要的阶段,但又不是必须的阶段
准备阶段:为类的静态变量分配内容,并且进行初始化。
1:进行内存的分配的时候仅包含static变量,不包含成员变量,成员变量是实例化对象的时候才会分配内存,static变量在方法区。而成员变量在堆区里面
2:这是设置默认值,包含数据类型的值,int设为0.string设为null,Object设为null,这个阶段数据默认值,并不会使用你的定义值,
解析:将类中的符号转化为直接引用
虚拟机将常量池的符号引用转化为直接应用。即把数据在堆中数据地址赋值给我们定义的变量名。
解析的动作主要包括:类,接口,字段,接口方法,方法类型
直接引用:直接指向目标对象的指针。
解析顺序并不一定按照图片中的顺序执行,有可能在初始化完了才会执行这个动作
初始化:给类的静态变量赋值,jvm负责对类进行初始化,主要对类的变量初始化。
1:声明变量的时候指定初始值
2:使用静态块来初始化
jvm判断:
假如当前类父类还没有初始化,先初始化父类
假如类中有初始化语句,一次执行初始化操作
成语变量初始化:反射,new、初始化子类时父类也会初始化
类的销毁:
System。exit(0)
程序正常运行结束
程序遇到异常终止的情况
对象的销毁:GC回收
《think in java》
类加载器
一共分为三类
1:启动加载器(bootstrap Classloader)主要负责加载存放在jdk/jre/lib文件夹下面的内容。并且能被jvm识别为类库。当前启动类加载器是无法直接被java程序应用
2:扩展加载器(extension Classloder)主要负责加载jdk/jre/ext目录。(java*)
3:应用程序加载器:(application Classloder)负责加载用户路径下的类,你操作系统配置环境变量,你在开发工具中写的java类。如果你没有自定义类加载器,默认一般都是使用它来加载
应用程序在运行过程中,时由上面三种加载器相互配合执行
图中方向并非继承,而是组合
加载机制
1:全盘负责:当一个类加载器负责加载某个class的时,如果这个class所依赖 的其他class也由当前这个类加载器负责
2:父类委托:先让父类加载器加载类容,只有父类加载器无法加载的时候在尝试自己从类路径中加载
3:缓存机制:缓存机制主要是保证已经加载过的类被缓存起来,当下次要用的时候,直接从缓存区获取就行了。一旦修改了Class,必须重启jvm才能生效
类加载
jvm启动的时候由jvm来加载
类名.class.getLoader()得到当前类的类加载器
类加载器.loderClass()方法加载类
class.forName(类的全限定名)也可以加载类
双亲委派模型:
工作流程:
1. 当ApplicationClassloader加载一个class的时候,首先自己不会尝试加载这个类,而且将类加载委托给父类 extClassLoader,
2. 当EXTClassload加载一个class的时候,它首先不会尝试自己去加载,而且将当前类交给BootStrapClassload,
3. 此刻交给BootStrapClassloader加载,但是如果加载失败,?Jre/lib获取不到类信息,又会委托EXTBoostarp来记载,
4. EXT加载失败,这个时候才会交给AppicationClassloader加载。如果AppicationClassloader也加载失败了。直接抛异常。ClassNotFoundException。
双亲委派模型的意义:
防止内存中出现的多份同样的字节码
保证java程序运行稳定
一个Class加载一次
反射
1:类加载Class.forName(“类的全限定名称”) 类加载器.loaderclass(“类名”)
类表现的面向对象中封装的特征。万物皆对象
那么类是对象吗?
类也是对象。类是java.lang.Class的对象
2:3什么是动态加载?什么是静态加载?
java中类的加载或者对象的加载,一种是静态加载,一种是动态加载
静态加载:在类编译的时候就已经在内存中加载了。new对象
动态加载:在类运行的时候才会主动去加载,反序列化,反射产生对象
优缺点:
静态加载,在编译的时候就加载,以后要用的时候不需要在编译。但是消耗内存
动态加载:在编译的时候不会加载对象,而是需要某个功能在加载,不会浪费内存资源,效率更低。
在项目开发中两种方式都会用,一般来说框架的底层大量要用动态加载
3:Class获取方式
java.lang.Class存放在堆中,在获取当前类对象提供了三种方式
Object .gteclass()所有对象都会由的方法
对象的静态属性 calss静态属性任何一个对象都有
class c =Class.forName(”类的全路径“);
总结:在运行期间,一个类只会产生一个Class队象,第一个方式获取的类对象意义不大,必须由对象才能反向获取。第二个方式需要导入 当前对象,依赖性太强,第三种方式只需要知道类的名称(String)姐u可以获取到类类型了
反射的操作:
通过反射可以获取到构造方法并使用
通过Class对象获取到某个类中的:构造方法,成员变量,成员方法