[jvm解析系列][一]Java内存区域分配和内存溢出异常OOM

原创 2016年06月02日 10:48:18

学过操作系统的同学应该比较清楚,一个操作系统必须要有完善的内存管理系统(页/段式的管理),相应的jvm全称java虚拟机应该也有类似的一种管理内存的方式,这种方式是建立在真实的操作系统内存管理方式之上的,他把内存分配成了不同的区域,形成了java内存模型。

那么,对于其他博客讲解这种题目要先抛一个图解出来,我并不想这样。因为这种模型的出现肯定是要解决问题的,我们需要顺延着前人设计jvm内存模型的脚步,看看到底为什么要这样设计,才能更好的理解它。

首先,我们思考一下,java需要什么区域呢?

1、必不可少的,一个程序计数器,用来记录当前程序运行的字节码指令,jvm使用了栈而不是寄存器结构(往后看相信你会理解的)。对于线程来讲,每个线程肯定是需要记录自己的执行位置,所以程序计数器是线程私有的

2、既然有了程序计数器我们还需要一个区域来存放当前运行的程序,那就是Java虚拟机栈,每一个方法的执行就会添加一个栈帧在虚拟机栈里(如果想要详细的了解栈帧请关注博客,随着系列的加深,我会一个个讲解)。对于线程来讲虚拟机栈同样的是线程私有。

3、一样的常用jvm的都知道还有一种jni的调用,为了这种方法的运行,设计了一种跟java虚拟机栈的双胞胎区域叫本地方法栈,除了运行native方法外其他的几乎一致。(在有的虚拟机里不区分native和java)

4、大家都知道java是面向对象的,既然方法都出来了,那么类存储在那呢?没错,jvm也分化出来了这样的一个区域叫做方法区(也称为永久代,因为这个区域很长时间不会发生gc)。这个区域里存储了虚拟机家在的所有的类信息,常量和静态变量等。(内含一个运行时常量池主要用于存放编译器生成的字面量和符号引用)他是线程公有的。

5、如果类都有了,那么对象呢?没错这就是jvm的重头戏,很多工作都在这个地方完成,他就是传说中的java堆,在有的地方甚至把jvm笼统的分为堆栈,可见java堆的重要性。java堆里面存放了几乎所有的对象实例,在java虚拟机规范中这样说:所有的对象实例和数组都要在堆上分配。随着JIT编译器等的发展也不那么绝对了。(java堆仍然很复杂,后期单开一篇博客详解)。它肯定是线程公有的。

6、到这里,好像java所有的需要都被分配了,以前确实是的,但是在JDK1.4之后,java引入了nio技术(不在本章范围内讲解),这就要求需要分配一个新的区域,没错,他叫直接内存。值得一提的是,这一区域并不是jvm的规范中的一部分,也不是虚拟机运行时数据区的一部分,但是他会引起OOM。

那么至此所有的内存区域分配完毕,配图如下帮助理解,相信你已经差不多的了解和理解了jvm分配的方式和目的了。

内存区域分配配图


上节说到~jvm的内存分配,所以对应的应该有6种溢出方式,实际上程序计数器一般不会溢出,我又把两个方法栈合在一起讲,所以溢出的可能性有4种

嘿嘿嘿嘿,我要去考试了,等我回来再补吧~

回来了继续补

1、Java堆溢出

java堆溢出一般都是因为在for或者递归里调用了太多次new对象的操作,并且可以被GCROOT查找到不能GC,而导致java堆内存不足报错,报错一般如下:

OutOfMemoryError:Java heap spce

2、虚拟机栈和本地方法栈溢出

虚拟机栈和本地方法溢出一般也是陷入了无限循环里并且在无限循环里一直在调用一个方法,因为一般情况下栈深能有1000~2000,报错一般都是StackOverflowError,OOM反而不常见,在处理这种异常时很棘手,需要减少其他区域的内存,因为这块内存是用总内存减去堆和方法区得到的。报错如下:

StackOverflowError.

3、方法区和运行时常量池溢出

这个区域想要溢出单单使用创建类的方法和常量是困难的,所以可以使用String.intern()方法直接将字符串加入到常量池。报错一般如下

OOM:PermGen space

4、本机直接内存溢出

由于上文知道直接内存一般用于NIO操作,所以使用了native方法而且因为这个区域的特殊性Heap dump并没有明显的报错。错误信息如下:

OutOfMemory。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java内存区域模型、对象创建过程、常见OOM

本文内容来源于《深入理解Java虚拟机》一书,非常推荐大家去看一下这本书。最近开始看这本书,打算再开一个相关系列,来总结一下这本书中的重要知识点。呃呃呃,说好的那个图片请求框架呢~  不要急哈,因...
  • u014082714
  • u014082714
  • 2016年06月27日 21:31
  • 1395

jvm内存不足解决

原来在服务器上部署的程序跑的很好,最近由于数据量剧增,报了些错误,没办法只好跟踪下源程序。可惜不太给力,由于数据量过大在eclipse 中调试的还没怎么调几下就Caused by: java.lang...
  • ZHANGBINFLY
  • ZHANGBINFLY
  • 2011年06月21日 21:02
  • 3873

故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

背景起因: 记起以前的另一次也是关于内存的调优分享下 有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡。 我按经验开始调优,在每个关键步骤的加入如下代...
  • u010602357
  • u010602357
  • 2017年01月09日 10:03
  • 1973

解决: Eclipse 提示内存不足

内存不足的提示了。 提示大概如下: MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memor...
  • bigtree_3721
  • bigtree_3721
  • 2016年07月29日 15:11
  • 7022

Java内存各部分OOM出现原因及解决办法

一,jvm内存区域 1,         程序计数器 一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器。 2,         java栈 与程序计数器一样,java栈(虚拟机栈)也是...
  • ls5718
  • ls5718
  • 2016年09月02日 09:58
  • 1171

JVM内存区域分区及OOM分析

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来。   概述: 对于从事C、C++程序开发的开发人员来说,在内存管理领域,他们...
  • qq_15465097
  • qq_15465097
  • 2016年04月21日 20:35
  • 476

【深入Java虚拟机】之一:Java内存区域与内存溢出

Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器、Java虚拟机栈、本地方法栈、Java...
  • mmc_maodun
  • mmc_maodun
  • 2013年12月30日 08:20
  • 33189

Java JVM:内存溢出问题

包括: 一. 栈溢出(StackOverflowError) 二. 堆溢出(OutOfMemoryError:java heap space) 三. 永久代溢出(OutOfMemoryErr...
  • Allen215902
  • Allen215902
  • 2016年02月17日 15:04
  • 973

JVM内存设置参数分析

引言:JVM提供了诸多的参数进行JVM各个方面内存大小的设置,为Java应用进行优化提供了诸多的工具,本文将会详细分析各个参数的功能与使用。...
  • blueheart20
  • blueheart20
  • 2016年08月02日 14:33
  • 2148

深入学习JVM内存设置原理和调优

你知道JVM内存设置原理吗,这里和大家分享一下,因为如果默认的java虚拟机的大小比较小,在对大数据进行处理时java就会报错:java.lang.OutOfMemoryError。 ...
  • zongrongna
  • zongrongna
  • 2016年06月03日 16:41
  • 5318
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[jvm解析系列][一]Java内存区域分配和内存溢出异常OOM
举报原因:
原因补充:

(最多只允许输入30个字)