JVM模型及内存溢出
一、JVM截图及概念

图1:JVM虚拟机运行时数据区域概念模型
1、程序计数器:内存空间中的一块小区域,作为当前线程所执行的字节码的行号指示器,注:如果是native方法,计数器为空
2、虚拟机栈:线程私有,生命周期与线程相同,虚拟机栈描述的是Java方法执行的内存模型:创建栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息
3、本地方法栈:和虚拟机栈功能类似,虚拟机使用本地Native方法服务
4、Java堆:线程共享,用于存放对象,是GC的主要管理区域
5、方法区:线程共享,用于存储已被虚拟机加载的类信息,变量,静态变量,即时编译器编译后的代码等数据
6、运行时常量池:编译期生成的各种字面量和符号引用
7、直接内存:直接内存不属于虚拟机运行时数据区的一部分,但是这部分内存也会被频繁的使用,而且也会导致OutOfMemoryError的异常
在JDK1.4中引入的NIO类中,有一种基于通道和缓存区的I/O方式,可以使用native函数直接调用堆外内存,然后使用Java堆中的DirectByteBuffer对象来引用操作,可以提高JVM的性能
二、JVM中对象的创建
当JVM解析,遇到new指令时,JVM首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个类是否被加载、解析和初始化过。
如果没有,那必须先执行相应的类加载过程(加载,验证,准备,解析,初始化),在类加载检查通过后,JVM会对新生对象在Java堆中分配内存,内存的大小在类加载完成后才能够完全确定。Java内存的分配方式有:指针碰撞和空闲列表,他们的分配原则是根据JVM中堆是否规整决定的。
对象在内存中的布局可以分为3块区域:对象头(运行时数据【哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳】,类型指针【指向类元数据指针】)、实例数据和填充
三、JVM中对象的访问
在JVM中对象的访问主要使用:句柄和指针

图2:使用句柄访问对象

图3:使用指针访问对象
两种对象访问方式各有优势,使用句柄来访问的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销。HotSpot虚拟机使用的是直接指针访问的方式。句柄来访问的情况也十分常见。
四、Java中出现OutOfMemoryError的情况
在图1的JVM虚拟机运行时数据区域概念模型中存在程序计数器、虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存,除了程序计数器,其他的部分如果操作不当都会产生运行时内存溢出的问题,下面将对虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存的溢出情况作阐述:
1、Java堆溢出
一般创建的对象在堆中容纳不下就会溢出,当抛出内存溢出问题时,需要进一步确定到底是内存泄露还是内存溢出,如果是内存泄露,那么进一步通过工具查看泄露对象到GC Roots的引用链,找到泄露代码的位置;如果是内存溢出,那么可以在物体机器中调大堆参数(-Xmx和-Xms),也需要检查代码中是否存在某些对象生命期过长、持有状态时间过程的情况,尝试减少程序运行期的内存消耗
2、虚拟机栈和本地方法栈溢出
虚拟机栈和本地方法栈溢出原因可能有以下两种:StackOverflowError异常和OutOfMemory异常
注:在单线程条件下,无论是请求的栈深度大于虚拟机所允许的最大深度,还是内存溢出,虚拟机都会抛出StackOverflowError异常,多线程会出现内存溢出异常
故:在多线程导致内存溢出,在不能减少线程数量和更换虚拟机的情况下,只能通过减少最大堆和减少栈容量来换取更多的线程
3、方法区和运行时常量池溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述,所以在产生大量动态类时,方法区就会出现溢出。例如CGLib字节码增强和动态语言以外,还有大量JSP或者动态产生JSP文件的应用和基于OSGI的应用
4、直接内存溢出:略
JVM模型及内存溢出的更多相关文章
- JVM原理及内存溢出
JVM原理及内存溢出
- 【深入Java虚拟机】之一:Java内存模型与内存溢出
[深入Java虚拟机]之:Java内存区域与内存溢出 高速缓存模型如下: ----------------------------------------------------分割线-------- ...
- jvm中的内存溢出与内存泄露
内存溢出: 就是我们通常遇到的OutOfMemoryError异常,它俗理解就是内存不够,通常在运行大型程序时发生,当程序所需要的内存远远超出了JVM内存所承受大小,就会报出OutOfMemoryEr ...
- JVM探秘:内存溢出
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 在 Java 虚拟机内存区域中,除了程序计数器外,其他几个内存区域都可能会发生OutO ...
- JVM(2) Java内存溢出异常
在Java虚拟机运行时数据区中,除了程序计数器之外,虚拟机栈.本地方法栈.方法区和Java堆都有发生OutOfMemoryError(简称OOM)异常的可能. 一.Java堆溢出 Java堆用于存储对 ...
- JVM 中发生内存溢出的 8 种原因及解决办法
1. Java 堆空间 2. GC 开销超过限制 3. 请求的数组大小超过虚拟机限制 4. Perm gen 空间 5. Metaspace 6. 无法新建本机线程 7. 杀死进程或子进程 8. 发生 ...
- 深入理解jvm之内存区域与内存溢出
文章目录 1. Java内存区域与内存溢出异常 1.1. 运行时数据区域 1.1.1. 程序计数器 1.1.2. java虚拟机栈 1.1.3. 本地方法栈 1.1.4. Java堆(Java Hea ...
- JVM探秘2--详解内存溢出OutOfMemoryError异常
JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...
- BAT面试必问题系列:深入详解JVM 内存区域及内存溢出分析
前言 在JVM的管控下,Java程序员不再需要管理内存的分配与释放,这和在C和C++的世界是完全不一样的.所以,在JVM的帮助下,Java程序员很少会关注内存泄露和内存溢出的问题.但是,一旦JVM发生 ...
随机推荐
- WPF DataGrid数据绑定
<DataGrid Name="date_grid" Grid.Column="0" ItemsSource="{Binding Portinf ...
- Unable to bind to http://localhost:8080 on the IPv6 loopback interface: 'Cannot assign requested address'.
.net core+nginx警告: warn: Microsoft.AspNetCore.Server.Kestrel[0] Unable to bind to http://localhost:5 ...
- 将二维数组转换成一维数组(基于reduce)
reduce:不改变原数组,返回一个新的数组.就是遍历数组元素,从头开始,依次往下,第一个参数是上一次的返回值,第二个参数是下一个数组元素,首次的时候第一个和第二个参数分别是 array[0], a ...
- WCF和SOA的简介
1 什么是SOA:面向服务架构(service oriented architecture),他属于一种组件架构模式.SOA追求的是服务提供方和服务使用方的高度解耦. 服务必须是自解释的,也就是说必须 ...
- json树迭代
getArray(data){ for (var i in data) { if(data[i].disabled){ data[i].disabled = false } if(data[i].ch ...
- 4.SpringMVC 配置式开发-处理器映射器
处理器映射器 HandlerMapping HandlerMapping 接口负责根据request请求找到对应的Handler处理器及Interceptor拦截器, 并将它们封装在HandlerEx ...
- CHD-5.3.6集群上sqoop安装
Sqoop(发音:skup)是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ...
- 第三章、Django之路由层
目录 第三章.Django之路由层 一 路由的作用 二 简单的路由配置 三 分组 四 路由分发 五 反向解析 六 名称空间 七 django2.0版的re_path与path 第三章.Django之路 ...
- json-server
json-server 一个前端模拟数据的本地化服务器 安装 npm install -g json-server 查看是否安装成功 json-server -v 新建一个文件夹 在文件夹中新建db. ...
- 解决No module named 'sklearn.cross_validation'
sklearn中已经废弃cross_validation,将其中的内容整合到model_selection中 将sklearn.cross_validation 替换为 sklearn.model_s ...