Jvm内存区域和GC
运行时数据区域
线程私有
- 程序计数器 正在执行的字节码指令的地址(native方法时为undefined)
- Java虚拟机栈 存储栈帧(局部变量表,操作数栈,动态链接,方法出口)OOM,StackOverflowError
- 本地方法栈 与虚拟机栈类似,是native方法的栈
线程共享
- Java堆 存放对象和数组 OOM
- 新生带
- Eden
- Survivor * 2
- 老年代
- 新生带
- 方法区(永久代)存储已被虚拟机加载的类信息、常量、静态变量 OOM
- 运行时常量池 方法区的一部分,编译器生成的字面量和符号引用 OOM
直接内存
不是运行时数据区的一部分,但是也会产生OOM。
GC
垃圾检测
- 引用计数 实现简单且高效,但有循环引用的问题, 目前没有虚拟机的实现采用这个算法
- 可达性分析 从GC Roots(虚拟机栈、方法区静态属性、方法区常量、本地方法栈)开始,沿引用链向下搜索,没被引用链连接的对象就是无用对象
引用类型
- 强引用 代码中普遍存在的引用,只要强引用存在,被引用的对象就不会被回收
- 软引用
SoftReference,用来描述有用但并非必须的引用,如果一次GC之后内存仍然不足,会把这些对象列入回收范围进行第二次回收 - 弱引用
WeakReference,下次GC必定会被回收 - 虚引用
PhantomReference,不会对对象的生存时间产生影响,也无法通过虚引用取得对象实例,用于在对象被回收时收到一个通知
方法区
判断常量池中的对象是否需要回收与对象相似。
无用类的条件:
- 该类的所有实例都被回收
- 加载该类的类加载器已被回收
- 对应的Class对象没在任何地方被引用
垃圾回收
- 标记-清除
- 标记需要回收的对象,再统一回收
- 效率不高,内存碎片
- 复制
- 将内存分为两块,将存活的对象复制到to空间,将from空间统一清除
- 实现简单,运行高效,内存利用率低,存活率较高时复制效率低
- 新生代分为一个Eden和两个Survivor,默认大小比为8:1,每次只使用一个Survivor,GC时将新生代存活对象放到未使用的Survivor,放不下的晋升老年代(分配担保)
- 标记-整理
- 标记后将存活对象朝一边移动,清理掉端边界外的内存
分代收集
根据对象存活周期的不同,将内存划分为几块。新生代使用复制算法,老年代使用标记整理
Stop The World
可达性分析必须在一个能确保一致性的快照中进行,因此在GC进行时需要停止用户线程。
安全点和安全区域
可达性分析的耗时较久(方法区就可能有几百兆),因此使用了一组OopMap的数据结构,来存储特定位置上对象内什么偏离量上是什么类型的数据,这样在GC扫描时就可以直接获得这些信息。
但是会使OopMap内容变化的指令很多,如果每条指令都生成对应的OopMap,空间成本会非常高,因此只记录了特定位置的信息,这些位置就称为安全点,线程只有到达安全点才能暂停。
具有方法调用、循环跳转、异常跳转功能的指令才会产生安全点。
- 抢先式中断(几乎没有虚拟机实现使用) GC发生时,中断所有线程,如果有线程不在安全点,恢复线程,让它跑到安全点
- 主动式中断 不直接操作线程,而是在安全点检查中断标志,判断是否需要暂停
安全区域是安全点的扩展,引用关系不会变化的一段代码片段。线程进入安全区域时,标示自己进入了安全区域,要离开时则检查根节点枚举或整个GC过程是否完成,没有则等待到收到可以离开安全区的信号。
垃圾收集器
- Serial
- 新生代单线程收集器
- 垃圾回收时只有GC线程在工作
- ParNew
- Serial的多线程版本,
- 垃圾回收时只有多个GC线程在工作
- Parallel Scavenge
- 新生代收集器,
- 并行的多线程收集器,
- 可控制的吞吐量(吞吐量优先)
- Serial Old
- Serial的老年代版本
- Parallel Old
- Parallel Scavenge的老年代版本
- CMS
- 老年代收集器,
- 使用标记清除算法,
- 追求最短回收停顿时间,
- 只在初始标记阶段(只记录GC Roots能关联到的对象)和重新标记阶段(修正并发标记时发生的引用变化,多线程)会STW,
- 对CPU资源敏感,并发时占用一定资源,程序变慢,吞吐量变低
- 无法清理浮动垃圾,需要预留一定空间在并发收集时供用户线程使用,如果预留空间不够,会临时启用Serial Old重新进行收集
- 内存碎片,找不到足够大的连续内存时,提前触发一次Full GC,可以设置在要进行Full GC,进行一次随便整理(或每几次不压缩的Full GC,整理一次碎片)。
- G1
- 新生代和老年代收集器,面向服务端应用的垃圾收集器
- 并行并发、分代收集、空间整合、可预测停顿
- 将堆分为多个大小相等的独立区域,新老生代不再物理隔离,
- 有计划的避免在整个堆做垃圾回收,优先回收价值最大的区域
- 追求低停顿可尝试,追求吞吐量无优势
分配和回收策略
- 对象优先在Eden分配
- 大对象直接进入老年代 避免在Eden和Survivor中复制大量内存
- 长期存活对象进入老年代 每经历一次GC,对象的年龄+1,达到一定岁数就晋升老年代
- 动态对象年龄判断 Survivor中,相同年龄的所有对象大小总大于Survivor的一半,年龄大于等于该年龄的对象晋升老年代
- 空间分配担保 Survivor空间不足,晋升老年代,有老年代空间不足风险;老年代连续空间小于新生代对象总大小或历次晋升平均大小就会进行Full GC
其他
finalize()
忘掉这个方法
参考资料
《深入理解Java虚拟机》第2版
《Java虚拟机规范》Java SE 8版
Jvm内存区域和GC的更多相关文章
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java系列笔记(3) - Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- JVM基础知识(1)-JVM内存区域与内存溢出
JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...
- JVM内存区域模型
一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代” .“非堆” ,"perm", 它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共 ...
- JAVA内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java 内存区域和GC机制-java概念理解
推荐几篇关于java内存介绍的文章 Java 内存区域和GC机制 http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html ...
- Java内存区域和GC机制篇
Java内存区域和GC机制一.目录 1.Java垃圾回收概括 2.Java内存区域 3.Java对象的访问方式 4.Java内存访问机制 5.Java GC 机制 6.Java垃圾收集器 二.Java ...
- 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控
如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...
- 【转载】Java系列笔记(3) - Java 内存区域和GC机制
Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...
随机推荐
- Jquery Ajax自定义无刷新提交表单Form
Jquery的$.ajax方法可以实现ajax调用,要设置url,post,参数等. 如果要提交现有Form需要写很多代码,何不直接将Form的提交直接转移到ajax中呢. 以前的处理方法 如Form ...
- HDU 1556 Color the ball (树状数组 区间更新+单点查询)
题目链接 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽&quo ...
- 软件测试工程师人手必备的一只:TOM猫,可以带你装逼带你飞!
Hi,你来了? 其实没有猫,为了让你们好好学习,天天向上!我可真的是拼了命了! 写这篇文章的缘由是,近期有同学经常问到一个这样的问题: 老师,tomcat是啥? 老师,Linux是啥? 老师,xshe ...
- webpack详解
webpack是现代前端开发中最火的模块打包工具,只需要通过简单的配置,便可以完成模块的加载和打包.那它是怎么做到通过对一些插件的配置,便可以轻松实现对代码的构建呢? webpack的配置 const ...
- UNIX环境高级编程 第11章 线程
使用C++调用pthread_cleanup_push( )时,下面的代码是无法编译通过的: pthread_cleanup_push(cleanup, "thread 1 first ha ...
- spring-boot-CommandLineRunner
在项目服务启动完成后就去加载一些数据 @Component public class MyStartupRunner1 implements CommandLineRunner { @Override ...
- TCP三次握手与四次挥手过程
TCP连接的建立(三次握手) 首先,客户端与服务器均处于未连接状态,并且是客户端主动向服务器请求建立连接: 客户端将报文段中的SYN=1(同步位),并选择一个seq=x,(即该请求报文的序号为x) ...
- 虚拟环境pipenv的使用
安装虚拟环境 安装python3.6 python -m site --user-base 找到 用户基础目录 指定python版本的方式 pipenv --python 3.8 安装 用户范围内安装 ...
- python 中的__del__
# -*- coding: utf-8 -*- # @Time : 2018/9/19 20:21 # @Author : cxa # @File : delDemo.py # @Software: ...
- OpenStack 监控解决方案
正如你们看到的那样,到目前为止(OpenStack Kilo),OpenStack自己的监控组件Telemetry并不是完美, 获取的监控数据以及制作出来的图表有时候让人匪夷所思,因其重点并不是监控而 ...