目录
JVM基础构成
晋升说明
- 大字符串或者大数组
- 默认15个轮回,新生代对象就会进入老年代
- 如果一个survior中所有一样年龄对象的大小总和大于survior空间的一半,大于这个年龄的对象也会直接进入老年代
方法区
1、类元数据就是放在这个里面的,比如class的信息。
2、常量和静态变量也是放在这个里面的
3、如果满了 会报如下异常java.lang.OutofMemoryError:PermGen space 或者java.lang.OutOfMemoryError:Metaspace
常用的垃圾回收器-CMS垃圾回收
CMS垃圾回收器只处理老年代和持久代,常见的组合是parelNew + cms处理整个堆的垃圾回收
是标记清除的一种实现,有参数可以设置清楚后整理减少碎片
GCRoots对象
- 常量池中常量引用的对象
- 方法区中静态属性引用的对象
- 栈里面的引用的对象
CMS工作图示
1、初始标记:标记GC Roots可以直接关联到的对象,速度很快(stw)
2、并发标记:可达性遍历,这个时候用户线程也是一起执行的
3、重新标记:为了修正并发标记期间,因程序运行导致标记产生变动的对象。(stw)
4、并发清除:清除垃圾,和用户线程一起处理
类加载过程
加载阶段:
1.通过一个类的全限定名来获取定义此类的二进制字节流。
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3.在Java堆中生成一个代表这个类的java.lang.class对象,作为方法区这些数据的访问入口。
验证阶段:
1.文件格式验证(是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理)
2.元数据验证(对字节码描述的信息进行语意分析,以保证其描述的信息符合Java语言规范要求)
3.字节码验证(保证被校验类的方法在运行时不会做出危害虚拟机安全的行为)
4.符号引用验证(虚拟机将符号引用转化为直接引用时,解析阶段中发生)
准备阶段:
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段。将对象初始化为“零”值
解析阶段:
解析阶段时虚拟机将常量池内的符号引用替换为直接引用的过程。
就是能找到方法,对象,常量的具体内存中的位置
初始化阶段:
初始化阶段时加载过程的最后一步,而这一阶段也是真正意义上开始执行类中定义的Java程序代码。
对于初始化阶段,虚拟机严格规范了有且只有 5 种情况下,必须对类进行初始化(只有主动去使用类才会初始化类):
1、当遇到 new 、 getstatic、putstatic 或 invokestatic 这 4 条直接码指令时,比如 new 一个类,读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。
当 jvm 执行 new 指令时会初始化类。即当程序创建一个类的实例对象。
当 jvm 执行 getstatic 指令时会初始化类。即程序访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)。
当 jvm 执行 putstatic 指令时会初始化类。即程序给类的静态变量赋值。
当 jvm 执行 invokestatic 指令时会初始化类。即程序调用类的静态方法。
2、使用 java.lang.reflect 包的方法对类进行反射调用时如 Class.forname("..."), newInstance() 等等。如果类没初始化,需要触发其初始化。
3、初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。
4、当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。
5、MethodHandle 和 VarHandle 可以看作是轻量级的反射调用机制,而要想使用这 2 个调用, 就必须先使用 findStaticVarHandle 来初始化要调用的类。
6、当一个接口中定义了 JDK8 新加入的默认方法(被 default 关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,那该接口要在其之前被初始化。
双亲委派机制
打破类加载器的双亲委派机制_-带三个表-的博客-CSDN博客
附