jvm内存模型
jvm的五大内存区域
1、程序计数器
2、方法区(也称为永久代,后续被Metaspace取代)
3、虚拟机栈
4、本地方法栈
5、堆
1、程序计数器
记录线程的执行位置,线程私有内存
在多线程的情况下,线程被切换回来的时候能够知道该线程上次运行到哪儿了
2、方法区
方法区是所有线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量
放在永久代中经常会出现内存溢出,即PermGen Space异常,所以用元空间取而代之
元空间直接使用本地内存,理论上电脑有多少内存它就可以使用多少内存,所以不会再出现PermGen Space异常
java虚拟机对方法区比较宽松,可以选择不实现垃圾收集
3、虚拟机栈(stack)
每个线程都有各自的Java虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡.
Java虚拟机栈会为每一个即将运行的Java方法创建“栈帧”,用于存储局部变量表、操作栈、动态连接、方法返回地址等
每个方法从开始调用到执行完成的过程,就是栈帧从入栈到出栈的过程
如果方法A调用了方法B,那么A就会先入栈创建一个栈桢,接着B再入栈成为栈顶,B执行完先出栈,接着A执行完出栈。
Java虚拟机栈可能出现两种类型的异常:
1、线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError。
2、虚拟机栈空间可以动态扩展,当动态扩展是无法申请到足够的空间时,抛出OutOfMemory异常。
4、本地方法栈
本地方法栈和Java虚拟机栈实现的功能与抛出异常几乎相同
只不过虚拟机栈是为虚拟机执行Java方法服务,本地方法栈则为虚拟机使用到的本地方法服务.
线程开始调用本地方法时,会进入一个不再受JVM约束的世界
本地方法可以通过JNI(Java Native Interface)来访问虚拟机运行时的数据区
5、堆(heap)
堆区是所有线程共享的内存区域
堆是OOM故障最主要的发源地,它存储着几乎所有的实例对象
通常情况下,它占用的空间是所有内存区域中最大的,但如果无节制地创建大量对象,也容易消耗完所有的空间
堆的内存空间既可以固定大小,也可运行时动态地调整,通过如下参数设定初始值和最大值
-Xms256M. -Xmx1024M
其中,-X表示它是JVM运行参数,ms是memorystart的简称 最小堆容量,mx是memory max的简称 最大堆容量
但是在通常情况下,服务器在运行过程中,堆空间不断地扩容与回缩,势必形成不必要的系统压力,
所以在线上生产环境中,JVM的Xms和Xmx设置成一样大小,避免在GC后调整堆大小时带来的额外压力
堆分成两大块:新生代和老年代(默认空间比例为1:2)
新生代分为三块:Eden区、From Survivor区和To Survivor区(默认空间比例为8:1:1)
对象产生之初在新生代,步入暮年时进入老年代,但是老年代也接纳在新生代无法容纳的超大对象
Survivor区每个对象都有一个计数器,每次YGC都会加1,默认加到15次,就要移送到老年代
Eden区 -> Survivor 0区 -> Survivor 1区 -> 老年区的过程
1、所有对象都在伊甸园出生,当伊甸园占满时,开始进行一次Young GC,此次GC会将已存活的对象复制到S0区中
2、伊甸园区又被占满时,此时又进行一次Young GC,伊甸园存活的对象又复制到S0区。
3、在若干次Young GC后,幸存区S0也满了,此时Young GC会对伊甸园和幸存区S0的做一次垃圾回收,将两个区存活的对象复制到幸存区S1中,再把伊甸园和S0清空,最后把S1的内存与S0交换,此时S1又腾空了,S0剩下一些老对象。
4、又经历若干次GC,幸存区S0已经放满了经历过N次GC都回收不了的老对象,此时会将老对象复制到老年代中,腾空伊甸园和幸存区。
(并非当幸存区被老对象占满才复制到老年代中,当老对象年龄达到15岁,即经历过15次GC都还活着的,也会复制到老年代中)
(另外伊甸园中如果诞生了一个比幸存区还大的对象,那么该对象回收不了时,也会直接送入到老年代中)
5、又经历过若干次GC后,老年代也满了,那么此时它会进行一次Full GC。
6、当执行Full GC后,老年代还是放不下新来的对象时,就会抛出OOM
堆特点
Java虚拟机所需要管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建
堆是垃圾回收的主要区域,所以也被称为GC堆.
当线程请求分配内存,但堆已满,且内存已满无法再扩展时,就抛出OutOfMemoryError
原文地址:https://www.cnblogs.com/jis121/p/11045186.html
- .NET DLR 上的IronScheme 语言互操作&&IronScheme控制台输入中文的问题
- Java中Map相关的6大问题——每个开发人员都要注意
- android service 学习(下)
- 混淆漏洞CVE-2017-0213技术分析
- android service 学习(上)
- 黑帽SEO剖析之隐身篇
- Java中如何判断一个字符串是Java代码还是英文呢?
- 将复杂查询写到SQL配置文件--SOD框架的SQL-MAP技术简介
- Java中实现找到两个数组交集的2种方法,开发实用
- Java Web中JSP的include 指令知识点总结——每日一语法学习
- Java反序列化漏洞从理解到实践
- ORM查询语言(OQL)简介--高级篇(续):庐山真貌
- Java中使用Hibernate系列之映射关联启动工作学习(第五节)
- Java中使用Hibernate系列之单向Set-based的关联学习(第四节)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Java——引用传递实例分析(进阶分析、对象比较、类与类的关联实现)
- JavaWeb——JQuery之基本概述与快速入门实践总结(JQuery各版本区别、JQuery对象和JS对象的区别与转换)
- Java——动态代理设计模型概述(实现步骤、增强方式)与代理商采购电脑模拟程序实战
- Java——this关键字(调用本类属性、调用本类方法、表示当前对象)
- 5分钟玩转Lighthouse|零基础也能拥有WordPress个人博客
- Java——String类常用方法总结,看这一篇就够啦(比较、查找、截取、替换、拆分、其他)
- Java——深入分析类与对象(封装性、构造方法与匿名对象、简单Java类开发原则)
- Java——类与对象(基本概念、定义、内存分析、引用传递)
- Java——Stream数据流
- JavaWeb——MyBatis框架之连接池原理、MyBatis事务提交设置、动态SQL语法总结
- 8种ETL算法归纳总结,看完这些你就全明白了
- JavaWeb——Maven基础之详细总结,从零开始搭建Maven工程,包含一些常见的坑org.eclipse.jdt.internal.compiler.classfmt.ClassFormatEx
- JavaWeb——Redis数据库之Jedis操作5种类型数据的使用总结与前端Ajax获取Redis缓存数据的案例实战(结合了MySQL数据库)
- Java——数据库编程JDBC之快速入门吐血总结及各关键对象详解(提供了JDBCUtils工具类)
- MySQL数据库——事务的操作(开启、回滚、提交)、特征、隔离级别基础总结