Java基础
- Javac 编译Java文件成为。class文件
- javap 是jdk自带的反编译工具
JVM 如何加载.class文件
- ClassLoader: 依据特定的格式将文件加载到内存
- Execution Engine: 对命令进行解释
- Nactive Interface: 融合不同开发语言的原生库为Java所用
- Runtime Data Area: Java内存空间模型
反射
Class:
- 是一个类; 一个描述类的类.
- 封装了描述方法的 Method,
- 描述字段的 Filed,
- 描述构造器的 Constructor 等属性.
如何得到 Class 对象:
- Person.class
- person.getClass()
- Class.forName(“com.atguigu.javase.Person”)
Method:
如何获取 Method
- getDeclaredMethods: 得到 Method 的数组.
- getDeclaredMethod(String methondName, Class … parameterTypes)
如何调用 Method
- 如果方法时 private 修饰的, 需要先调用 Method 的 setAccessible(true), 使其变为可访问
- method.invoke(obj, Object … args);
Field:
如何获取 Field:
- getField(String fieldName)-
如何获取 Field 的值:
- setAccessible(true)
- field.get(Object obj)
如何设置 Field 的值:
- field.set(Obejct obj, Object val)
ClassLoader
BootStrapClassLoader(引导类加载器)
- 处于类加载器层次结构的最高层,负责 sun.boot.class.path 路径下类的加载,默认为 jre/lib 目录下的核心 API 或 -Xbootclasspath 选项指定的 jar 包。
ExtClassLoader (扩展类加载器)
- 加载路径为 java.ext.dirs,默认为 jre/lib/ext 目录或者 -Djava.ext.dirs 指定目录下的 jar 包加载。
AppClassLoader(系统类加载器)
- 加载路径为 java.class.path,默认为环境变量 CLASSPATH 中设定的值。也可以通过 -classpath 选型进行指定。
用户自定义 ClassLoader
- 可以根据用户的需要定制自己的类加载过程,在运行期进行指定类的动态实时加载。
双亲委托
- 每个classLoader都从自己已经加载的类中查询是否存在需要的类,如果存在直接返回已经加载的类,每个类加载器都有自己的加载缓存,当一个类被加载后,会直接放入缓存
- 当前classLoader中不存在,则委托给父加载器去加载,依次递归,一直到bootstrp ClassLoader
- 如果没有则从对应得目录中加载,从最高层向下加载;
优势
- 保证一个类的全局唯一性
类的加载
- 当程序主动使用某一个类时,如果该类没被加载到内存中,系统会经过加载,连接,初始化三个步骤来对类进行初始化, 一般JVM会连续完成三个步骤,所以三个各步骤统称为 类的加载或类初始化
类加载
- 类的加载时指将类的class 文件读入内存,并为之创建一个java.lang.Class对象,当程序使用任何类的时候 系统都会为之建立一个java.lang.Class对象
类的连接
- 当类被加载之后,系统为之生成一个对应得Class对象,接着将会进入连接阶段,连接阶段把类的二进制文件数据合并到JRE中
验证
- 验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
准备
类准备阶段则负责为类的类变量分配内存,并设置默认初始值
解析
将类的二进制数据中的符号引用替换为直接引用
对象分配规则
- 对象优先分配在Eden区,如果Eden区没有足够的空间时候,虚拟机执行一次Minor GC。
- 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)这样做的目的是避免Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)
- 长期存活的对象进入老年代,虚拟机为每个对象定义了一个年龄计数器,如果对象经过一次Minor GC 那么对象会进入Survivor区,之后每经过一次Minor GC ,那么对象的年龄增加1,直到达到阈值,对象进入老年代
- 动态判断对象的年龄.如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄的对象可以直接进入老年代
- 空间分配担保。每次进行Minor Gc的时候,JVM会计算Survior区移至老年区的对象的平均大小,如果这个值大于老年区的剩余价值大小进行一次FullGC, 如果小于 ,检查HandlePromotionFailure设置,如果true则只进行进行Monitor GC,如果false 则进行fullGC
LoadClass和forName的区别
-
类的加载过程分为 加载—链接(链接又分为验证,准备,解析三个阶段)—初始化
-
Class.forName得到的是已经初始化完成的,即类的加载过程已经完成了
-
而Class.loadClass得到的class是还没有链接的,即只是通过了类加载过程的加载阶段,通过ClassLoader加载class加载文件字节码,将其放在运行时数据区的方法区内,在堆区创建一个java.lang.Class对象(用来封装类在方法区内的数据结构)
-
在spring IOC中 大量使用这种加载方式,木的还是为了提高加载速度,而剩余的阶段则等到实际使用到类的时候才执行