1 2 3 4

反射

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对象获取到某个类中的:构造方法,成员变量,成员方法

 

posted @ 2019-05-04 14:52  startscorpio  阅读(155)  评论(0编辑  收藏  举报