-
线程公有:
- 方法区:java方法区和堆一样,方法区是一块所有线程共享的内存区域,他保存系统的类信息,比如类的字段,方法和常量池等,方法区的大小决定系统可以保存多少个类,如果系统定义的类太多,导致方法区溢出,虚拟机同样会抛出内存溢出的错误,方法区可以理解为永久区
- 堆:
- 有限分配Eden区,空间分配担保机制
- 大对象直接进入老年代,避免在Eden区和Servivor区之间产生大量的内存复制
- 对象晋升
- 年龄阈值:-XX:MaxTenuringThreshold,默认15
- 动态年龄判定:然而JVM并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代
- 如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,而无需等到晋升年龄
-
虚拟机栈
- 局部变量表
- 操作数栈
- 主要保存计算过程的中间结果,同时做为计算过程中的变量临时的存储空间
- 动态链接
- 方法返回地址
-
对象生死判定
- 可达性分析:
- 方法区:类静态属性引用的对象
- 常量引用的对象
- 虚拟机栈(本地变量表)中引用的对象
- 本地方法栈JNI(Native方法)中引用的对象
- 可达性分析:
-
垃圾回收算法
- 引用计数法
- 复制算法
- 标记清除算法
- 标记整理算法
-
垃圾回收器:
- serial串行
- paranew 并行
- cms并发
- G1
-
serial收集器
- Serial收集器+Serial Old收集器:简单高效
- 一个线程的收集器,在进行垃圾收集的时候,必须暂停其他所有的线程直到他结束收集为止
- 设置参数:-XX:+UseSerialGC
- 开启之后会使用Serial(Young区用)+Serial Old(Old区用)的收集器组合
- 表示新生代和老年代都会使用串行垃圾收集器,新生代使用复制算法
-
ParNew收集器
- 使用多线程进行垃圾回收,在垃圾收集时,会stw暂停其他所有的工作线程
- ParNew收集器其实就是Serial收集器新生代的并行多线程版本,最常见的应用场景是老年代配合CMS工作
- 设置参数:-XX:+UserParNewGC 启用ParNew收集器组合,新生代使用复制算法,老年代使用标记整理算法
- -XX:ParallelGCThreads限制线程数量,默认开启和CPU数目相同的线程数
-
Parallel Scavenge收集器:
- jdk8默认的垃圾回收器
- Parallel Scavenge收集器类似ParNew也是一个新生代垃回收器,使用复制算法,也是一个并行的多线程的垃圾回收器,俗称吞吐量优先级的垃圾回收器,一句话,串行垃圾收集器在新生代和老年代的并行化
- 他关注的是:
- 可控的吞吐量:用户代码运行时间 / (用户代码运行时间 + 垃圾收集的时间),吞吐量高意味着高效利用CPU的时间,他多用户后台运算而不需要太多的交互任务
- 自适应调节策略:这也是ParallelScavenge收集器与ParNew收集器的一个重要区别
- 自适应调节策略,虚拟机会根据当前运行情况收集性能控制信息,动态调整这些参数以提供最合适的停顿时间(-XX:MaxGCPauseMillis)
- 设置参数:-XX:+UserParallelGC或 -XX:+UseParallelOldGC(相互激活),开启该参数后,新生代适用复制算法,老年代使用标记整理算法
-
老年代:
- Serial Old收集器
- Parallel Old收集器
- CMS收集器
-
CMS收集器
- 优点:并发标记清楚,并发收集停顿,并发指的是与用户线程一起执行
- 缺点:CMS在收集与应用线程会同时增加对内存的占用,也就是CMS必须在老年代用尽之前完成垃圾回收,否则CMS回收失败时,会出现担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而造成较大的停顿时间
- 标记清除:产生大量空间碎片,-XX:CMSFullGCsBeForeCompaction来设置多少次full gc之后进行一次整理
- 参数设置:-XX:+UserConcMarkSweepGC开启该参数后,会自动将-XX:+UserParNewGC打开
- 开启参数后:ParNew(Young区用)+CMS(Old区用) + Serial Old的收集器组合(CMS出错后的备用收集器)
- 四个阶段:
- 初始标记:STW,只是标记一下GC root能直接关联的对象,速度很快,仍然需要暂停所有的工作线程
- 并打标记:和用户线程一起工作,不需要暂停工作线程,主要标记过程,标记全部对象,
- 重新标记:STW,对之前标记的对象进行二次确认
- 并发清除:和并发标记这两个阶段是最耗时的
- 特点:
- CMS收集器是一种以获取最短回收停顿时间为目标的收集器,这类应用尤其重视服务器的响应速度,希望停顿时间最短
- CMS非常适合对内存大,CPU核数多的服务器端应用,也就是G1出现之前大型应用首选的垃圾回收器
- 缺点:
- 无法处理浮动垃圾
- 标记-清除:产生大量空间碎片,当然可以设置多少次GC之后进行一次整理,=0的情况下,就变成了标记-整理
-
G1收集器
- 分区收集
- G1将整个JAVA堆划分为多个大小相等的独立区域(Region)
- 虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,他们都是一部分Region(不需要连续)的集合
- 分区:
- Eden区
- Survivor区
- Old区
- 超大对象区:如果一个对象占用的空间超过了分区容量的50%以上,G1收集器就认为这是一个巨型对象,这些巨型对象默认会直接分配到老年区,但是如果他是一个短期存在的巨型对象,就会对垃圾收集器产生负面影响,为了解决这个问题,G1划分了多个H区,专门用来存储巨型对象,如果一个H区存不下,会寻找多个连续的H区来存储,有时候没有连续的空间就进行Full GC
- 并发标记阶段:
- 在与应用程序并发执行的过程中会计算活跃度信息
- 这些活跃度信息标识出哪些Regions最适合在STW期间回收
- 不像CMS有清理阶段
- 再次标记阶段:
- 使用Snapshot-at-the-Beginning(STAB)算法比CMS快得多
- 空Region直接被回收
- 拷贝,清理阶段:
- 年轻代与老年代同时回收
- 老年代内存回收会基于他的活跃度信息
- G1收集器相对于CMS收集器的优点:
- G1在压缩空间方面有优势
- G1通过将内存空间分成区域(Region)的方式避免内存碎片问题
- Eden,Survivor,Old区不在固定,在内存使用效率上来说更加灵活
- G1可以通过设置预期停顿时间(Pause Time)来控制垃圾收集时间避免应用雪崩现象
- G1在回收内存后会立马同时做合并空闲内存的工作,而CMS默认是在STW的时候做
- G1会在Young GC中使用,而CMS只能在O区使用
-
JVM小工具
- jps:打印Hotspot VM进程,VMID,JVM参数,mian()函数参数,主类名/JAR路径
- jstat:查看Hotspot VM运行时信息,类加载,内存,GC(可分代查看),JIT编译
- jinfo:查看和修改虚拟机各项配置
- jmap:heapdump:生成VM堆转储快照,查询finalize执行队列,Java堆和永久代详细信息
- jstack:查看VM当前时刻的线程快照,当前VM内每一条线程正在执行的方法堆栈集合
- javap:查看经javac之后产生的JVM字节码代码
- jcmd:一个多功能工具,可以用来导出堆,查看java进程,导出线程信息,执行GC,查看性能相关数据等
- jconsole:可以查看内存,线程,类,CPU信息,以及对JMX MBean进行管理
- jvisualvm:可以监控内存泄漏,跟踪垃圾回收,执行时内存分析,CPU分析,线程分析
-
JVM异常
- java.lang.StackOverflowError:递归调用,容易导致栈溢出
- java.lang.OutOfMemoryError: Java heap space:对空间不足导致Java heap space
- java.lang.OutOfMemeryError: Direct buffer memory:nio磁盘不足导致direct buffer memory
- java.lang.OutOfMemoryError: GC overhead limit exceeded:频繁垃圾回收,却没有释放空间,导致GC overhead limit exceeded
- java.lang.OutOfMemoryError: unable to create new native thread:高并发unable create new native thread
- java.lang.OutOfMemeryError: Metaspace:原空间大小,只受本地内存限制
- java.lang.OutOfMemeryError: PermGen space:类或者方法不能被加载到老年代,他可能出现在一个程序加载很对类的时候,比如引用了很多第三方的库
- java.lang.OutOfMemeryError: Requested array size exceeds VM limit:创建的数组大于堆内存的空间
- java.lang.OutOfMemeryError: request bytes for . Out of swap space:同样是本地方法内存分配失败,只不过是JNI或者本地方法或者java虚拟机发现
java内存模型
最新推荐文章于 2024-07-13 13:55:40 发布