JVM

自动内存管理

运行时数据区

线程私有的:虚拟机栈、本地方法栈、程序计数器
线程共享的:方法区、堆

程序计数器

线程私有的区域,指向本线程下一条要执行的字节码。不会抛出OOM异常

虚拟机栈

为执行java方法提供服务,如果栈深度超过允许范围,会抛出StackOverflowError;如果允许虚拟机栈扩展,在申请不到内存无法进行扩展时,会抛出OutOfMemoryError

本地方法栈

为执行native方法提供服务,类似于虚拟机栈,也会抛出StackOverflowError和OutOfMemoryError

对象实例和数组分配内存要在堆上进行。会抛出OOM异常。
堆可以位于物理上不连续的空间,逻辑连续即可。
GC的主要区域

方法区

保存虚拟机运行过程中加载的类信息、常量、静态变量等。
无法分配内存时,抛出OOM异常
这个区域的GC只要回收无用常量、卸载类

对象的创建过程

类加载、分配内存(如何保证原子性?)、内存清零、设置对象头、init

对象的内存布局:对象头、实例数据、对齐填充

垃圾回收机制

自动垃圾回收需要考虑的三个问题:

  • 回收哪些内存?对象存活判断(引用计数、可达性分析)
  • 什么时候回收?
  • 怎么回收?

垃圾回收算法

标记-清除

空间碎片

复制算法

Eden:From Survivor:To Survivor=8:1:1
复制操作效率低

标记-整理

分代算法

新生代和老年代采用不同算法

垃圾收集器

CMS

Concurrent Mark Sweep,顾名思义,采用标记清除算法回收垃圾,工作在老年代,多线程。工作过程如下:

  • 初始标记(Stop The World):标记与GC Roots直接相关的对象
  • 并发标记:根据上一阶段的标记遍历标记
  • 重新标记(STW):处理上一阶段用户线程对内存做的改动
  • 并发清除

CMS的缺点:

  • 对CPU资源非常敏感
  • 浮动垃圾:并发清除阶段由用户线程产生的垃圾内存
  • 空间碎片:标记清除算法的缺陷

G1

Garbage-First,多线程,新生代和老年代不再物理隔离,将内存分区Region,新生代和老年代都由一系列的Region组成,维护Region的优先队列,每次优先回收价值大的Region(因此叫GarbageFirst),标记整理算法

工作过程:

  • 初始标记:STW,标记与GC Roots直接相关的对象
  • 并发标记:遍历标记
  • 最终标记:STW,修正
  • 筛选回收:STW,对Region根据回收价值和成本进行排序,按照用户期望进行回收

GC 分为两类:minorGC和major/fullGC。
minorGC发生在新生代,快;
fullGC发生在老年代,慢一个数量级

内存分配策略

自动内存管理可以分为两个模块:如何分配内存、如何回收内存

堆的分区

总体分为新生代和老年代
新生代采用复制算法回收内存,因此又可以分为三个区:Eden、From Survivor、To Survivor

jvm分配内存的常用策略

下面来看jvm分配内存的常用策略:

  • 对象优先分配在Eden区
  • 大对象直接进入老年代,利用担保机制
  • 长期存活的对象进入老年代:每个对象都有年龄,如果对象熬过第一次minorGC并且进入了Survivor区,则age=1;以后每次存活,age++;当age达到一定值之后,对象晋升老年代

新生代对象内存分配过程:首先查看eden区空间是否够用,不够用则进行一次minor gc到survivor区,如果survivor区也不够用,通过分配担保机制转移到老年代。

JVM调优

类加载

类加载是如何把字节码转换成运行时数据

类加载的过程

类加载分为:
加载、验证、准备、解析、初始化、卸载

其中加载、验证、准备、初始化、卸载这5个过程必须按顺序开始(而不是“完成”)

加载

加载过程做了什么?

  • 根据类全限定名获取二进制字节码
  • 将字节码转换为运行时数据结构放在方法区
  • 创建该类对应的Class对象

验证

验证字节码是否符合虚拟机规范

准备

类变量分配内存、置零

解析

符号引用转化为直接引用
符号引用:字面量
直接引用:地址

初始化

类构造方法 <clinit>(),由类变量赋值语句和static块合成

类加载器

类和它的类加载器共同确立了这个类在jvm中的唯一性

双亲委派模型

类加载器具有层次化,从上往下依次是:

  • 启动类加载器
  • 扩展类加载器
  • 应用类加载器

双亲委派模型的工作过程:
如果一个类加载器收到了一个类加载请求,它首先会把加载任务交给上一层类加载器,如果上层类加载器不能完成类加载,则由自己完成类加载。

破坏双亲委派模型

  • 重写loadClass()方法
  • 线程上下文类加载器 Thread Context ClassLoader
  • OSGi

并发

posted @ 2019-02-25 16:07  darknessplus  阅读(132)  评论(0编辑  收藏  举报