文章目录
说一下JVM内存模型
- 栈主要存放方法执行的本地变量、对象引用,方法执行前就先创建栈帧入栈,执行完出战
- 堆主要存放对象、数组,我们所说的新生代、老年代、永久代就是指这篇区域
- 方法区主要存放类定义(class文件),常量,静态变量。在JDK1.7中,HotSpotVM实现就是将其放到永久代中,这样的好处就是可以直接使用堆中的GC算法进行管理,坏处就是会会出现内存溢出,即PermGen Space异常。所以在JDK1.8中,HotSpotVM用元空间取代了永久代,成为 HotSpot VM 对方法区的实现,元空间直接使用本地内存,理论上电脑有多少内存它就会使用多少,避免发生PermGen Space异常。
- 程序计数器记录当前执行的代码行数
JDK 1.8 中,class对象和static成员变量,两者都位于堆(Heap),且static 成员变量位于 Class对象内
类的元数据存放在方法区
介绍一下垃圾回收算法有哪些
- 标记清除算法,它将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段首先通过根节点标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。然后再清除阶段,清除所有未被标记的对象
- 标记整理算法,从根节点开始扫描,标记出所有存活对象,并将这些存活对象复制到一块新内存,之后将原来那块全部回收掉。在垃圾对象多的前提下效率很高,在新生代经常发生
- 分代收集算法。目前虚拟机使用的回收算法,它解决了标记整理算法不适用老年代的问题,将内存分为各个年代。一般情况下将堆区分为新生代和老年代;堆区之外为永久代。
新生代垃圾对象多且占用内存少,可以使用标记整理算法;老年代垃圾对象少而且占用内存多,可以使用标记清除算法
如何判断一个对象是否可回收
首先判断其是否为不可达对象,如果是还要至少经历两次标记过程才会称为可回收对象。
判定为不可达对象策略是采用正向可达的方式,通过roots对象作为起点进行搜索,走过的路径称为“引用链”,当一个对象没有任何引用链相连时,证明此对象不可达,但不一定成为可回收对象。
能否被回收其实主要看finalize方法有没有与引用链上的对象进行关联,如果在finalize方法自救成功,则改对象为不可回收,否则可以进行回收
错误的垃圾回收机制会出现什么状况
CPU负载过高
系统报内存溢出异常
说一下CMS垃圾回收器和G1收集器的特点
CMS垃圾回收器
- 特点:
CMS基于“标记-清扫”算法实现,以获取最短回收成本为目标
工作流程是初始标记,并发标记,重新标记,并发清除。初始标记、从新标记这两个步骤仍然需要“stop the world”,初始标记只是标记一下GC Roots能直接关联到的对象,并发标记则是进行引用链的查找,重新标记是为了修正程序运行产生变化的数据标记 - 优缺点
CMS算法优点是:并发收集,低停顿
CMS算法缺点是:a) 占用cpu导致应用程序变慢,吞吐量降低
b) 无法在当此收集中处理浮动垃圾,只好等下一次GC进行清理
c) 产生大量空间碎片,大对象分配不足,可能会提前触发Full GC
G1垃圾回收器
- 特点:
a) G1充分利用CPU、多核环境,使用多个cpu锁定stop the world停顿时间
b) 分代收集,采用不同的方式处理不同代的对象
c) 空间整合,吸收"标记整理"算法的思想
G1运作工作流程是:初始标记,并发标记,最终标记,筛选回收
JVM类加载机制-热部署
JVM={类装载器+执行引擎+运行时数据区}
类加载机制分为 加载、连接、初始化三个阶段。
- 加载阶段,通过类装载器定位class文件,将class文件加载到内存,然后JVM实例读取类信息到方法区。
- 连接阶段,验证,准备(为类变量创建堆内存,并将成员变量初始化为默认值),解析(将符号引用转换为直接引用)
- 初始化,将成员变量进行初始化
注意点:任意一个类都是由这个类本身,和加载这个类的类加载器来确定的
双亲委派模型
- 启动类加载器(Bootstrap ClassLoader):用来加载%JAVA_HOME%/lib中的文件 或者 -Xbootclasspath指定的文件,属于虚拟机的一部分
- 扩展类加载器(Extension ClassLoader):用来加载%JAVA_HOME%\lib\ext目录中 或者 java.ext.dirs指定的类库,Java实现独立于虚拟机
- 应用程序类加载器(Application ClassLoader):用来加载用户类路径(classPath)上的类库,java实现独立于虚拟机
JVM类执行机制
是在class文件加载到JVM中并且产生Class对象之后,由JVM进解释执行(对比编译执行)