虚拟机是一种抽象化的计算机,Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
字节码文件也就是经过编译之后的class文件。
执行一个class文件,JVM中的类装载子系统首先会将class文件装载进入的内存区域(运行时数据区),再由执行引擎执行程序。
指的是将类的class文件的二进制数据读入到内存中,并将其放入到运行时数据区中的方法区内,并在堆区中创建一个对应的class对象。
类的初始化,包括生成对象的初始化和类的静态块的实例化。
初始化触发的时机: 类被直接引用(主动引用)的时候。
主动引用的情形有:
使用new关健字实例化对象
使用类的静态变量
使用类的静态方法
使用反射机制调用上述操作
程序入口 (调用main方法)
初始化顺序是:
静态块 -> 非静态块 -> 构造函数。
如果有父类,则初始化顺序是:
父类静态块 -> 子类静态块 -> 父类非静态块 -> 父类构造函数 -> 子类非静态块 -> 子类构造函数
被动引用不会触发类的初始化。
被动引用的情形:
在类使用完之后,满足下面的情形,会被卸载:
分为两大类:线程私有区域、线程共有区域
线程私有区域:
线程共有区域:
堆内存划分为年轻代,老年代。年轻代划分为eden区和survivor区,survivor区分为from区和to区;
大多数情况下,对象在eden区分配,eden区没有足够内存时,触发minorGC/YoungGC;
可通过配置-XX:PretenureSizeThreshold来设置直接进入老年代的阈值,这样可以避免大对象在Eden区创建,因为大对象比较大,会造成minorGC的效率下降。
虚拟机给每个对象一个年龄计数器,Eden区触发minorGC,存活对象复制到from区,此时对象年龄设为1,之后的每一次熬过一次minorGC,年龄都会加1,当年龄增加到一定程度(默认15,可通过XX:MaxTenuringThreshold=数字 参数可以设置对象在经过多少次minorGC后会被放入老年代)
这种情况时,JVM会将部分对象放入老年代,部分对象放入survivor区
默认8:1:1
survivor区的一批对象的总大小大于这块survivor区总大小的50%,大于等于这批对象中最大年龄的对象的对象,就能直接进入老年代。
这篇博客写到挺详细:
https://www.jianshu.com/p/989d3b06a49d