Java内存区域与内存溢出异常

运行时数据区域

程序计数器

  • 当前线程所执行的字节码的行号指示器
  • 当前线程私有
  • 不会出现OutOfMemoryError情况

java虚拟机栈

  • 线程私有,生命周期与线程相同
  • java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧,存储局部变量表(基本类型、对象引用)、操作数栈、动态链接、方法出口等信息
  • StackOverflowError异常:当线程请求的栈深度大于虚拟机所允许的深度
  • OutOfMemoryError异常:如果栈的扩展时无法申请到足够的内存

本地方法栈

与虚拟机栈相似,主要为虚拟机使用到的Native方法服务,在HotSpot虚拟机中直接把本地方法栈与虚拟机栈二合一

Java堆(Java Heap)

java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此区域的唯一目的就是存储对象实例。java堆是垃圾收集器管理的主要区域。java堆还可以细分为:新生代与老年代。在细一点有Eden空间、Form Survivor空间、To Survivor空间等。

  • 可以通过-Xmx和-Xms控制堆的大小
  • OutOfMemoryError异常:当在堆中没有内存完成实例分配,且堆也无法再扩展时。

方法区

  • 线程间共享
  • 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  • OutOfMemoryError异常:当方法区无法满足内存的分配需求时

运行时常量池

  • 方法区的一部分
  • 用于存放编译期生成的各种字面量与符号引用
  • OutOfMemoryError异常:当常量池无法再申请到内存时

直接内存

  • NIO可以使用Native函数库直接分配堆外内存,堆中的DirectByteBuffer对象作为这块内存的引用进行操作
  • 大小不受Java堆大小的限制,受本机(服务器)内存限制
  • OutOfMemoryError异常:系统内存不足时

HotSpot虚拟机

对象的创建

虚拟机遇到一条new指令时,首先将去检查这个对象的参数是否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,必须先执行类的加载过程。
在类加载检查通过后,虚拟机将为新生对象分配内存。对象所需内存大小再类加载完成后便可确定。内存分配可以采用“指针碰撞”与“空闲列表”的方式。

对象的访问定位

java程序需要通过栈上的reference数据来操作堆上的具体对象。访问方式有使用句柄和直接指针两种。

  • 句柄访问 java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息
  • 直接指针访问 java堆对象的布局中必须考虑如何放置访问类型数据的相关信息,reference中存储的就是对象地址

OOM异常的解决思路

生成Dump快照文件:

  • 通过jvm参数—XX:-HeapDumpOnOutOfMemoryError可以让JVM在出现内存溢出是Dump出当前的内存转储快照
  • 用jmap生产dump文件,win通过任务管理器查看tomcat的进程pid,linux用ps命令查看进程pid,然后用jmap命令

先通过内存映像分析工具(如Eclipse的Memory Analyzer)进行分析,常见的情况有:

  • 内存泄露,对象已经死了,无法通过垃圾收集器进行自动回收,通过找出泄露的代码位置和原因,才好确定解决方案;
  • 内存溢出,内存中的对象都还必须存活着,这说明Java堆分配空间不足,检查堆设置大小(-Xmx与-Xms),检查代码是否存在对象生命周期太长、持有状态时间过长的情况。

OOM异常示例:

12345678910111213141516171819202122
package oom;

import java.util.ArrayList;import java.util.List;

/** * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError* @ClassName: HeapOOM * */public class HeapOOM {    static class OOMObject{

    }

    public static void main(String[] args) {        List<OOMObject> list = new ArrayList<OOMObject>();        while(true){            list.add(new OOMObject());        }    }}

参考

《深入理解java虚拟机 JVM高级特性与最佳实践》

深入理解jvm之内存区域与内存溢出的更多相关文章

  1. 深入理解JVM之JVM内存区域与内存分配

    深入理解JVM之JVM内存区域与内存分配 在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处 ...

  2. 深入理解java虚拟机系列(一):java内存区域与内存溢出异常

    文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了開始.假设有什么错误或者遗漏,欢迎指出. 一.概述 先上 ...

  3. JVM内存区域与内存溢出异常

    Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...

  4. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

  5. 深入理解java虚拟机-第二章:java内存区域与内存泄露异常

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  6. 深入理解java虚拟机---->java内存区域与内存溢出异常

    2. java内存区域于内存溢出异常 2.1 概述: 对于C/C++而言,内存管理具有最高的权利,既拥有每一个对象的“所有权”,又担负着每一个对象生命开始到结束的维护责任. 对于java而言,则把内存 ...

  7. 深入理解Java虚拟机之Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  8. 深入理解Java虚拟机之图解Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  9. 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域  

随机推荐

  1. 简单的完全背包HDU1114

    今天广州下雨啦,不过没关系啦,反正我最近也都在刷题学习算法. 昨天做了五题01背包,今天还是背包,不过是完全背包,估计做动态规划要持续好一段时间,一开始选了一道简单题目啦. HDU1114,看了小一段 ...

  2. 把AS代码链接到fla文件

    在属性里找到类,输入AS脚本的文件名然后点击右边的编辑就可以打开编辑AS脚本的界面,下面为链接代码. package { import flash.display.MovieClip; public ...

  3. JavaScript学习心得(五)

    一时间 1970年1月1日是电脑常用的时间参考点,称为纪元(Epoch)或者UNIX时间戳(UNIX Epoch).JavaScript中的Date对象能够表示1970年1月1日子夜前后1亿天之内的任 ...

  4. <string> <string.h>

    在C++开发过程中经常会遇到两个比较容易混淆的头文件引用#include<string.h> 和 #include<string>,两者的主要区别如下: #include< ...

  5. python【第十四篇】HTML与CSS初遇

    概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏览器 ...

  6. python 中调用windows系统api操作剪贴版

    # -*- coding: utf-8 -*- ''' Created on 2013-11-26 @author: Chengshaoling ''' import win32clipboard a ...

  7. iOS: 学习笔记, 动态添加按钮

    1. 新建iOS -> Single View Application. 2. 个性控制器文件YYViewController.m(此处修改为你相应的控制器文件名) // // YYViewCo ...

  8. smali 语法之try catch语句

    # virtual methods .method public onClick(Landroid/view/View;)V .locals 4 .parameter "v" .p ...

  9. 修改虚拟机linux硬盘的大小

    一.概述 Ubuntu用了一段时间,系统已从原来的4G增长到8G,导致虚拟磁盘不够用,需要修改虚拟硬盘的大小. 但是,修改虚拟机硬盘的大小不像修改内存那么简单,操作一个滑动条就轻松搞定.要知道虚拟硬盘 ...

  10. Apache添加虚拟主机目录

    <VirtualHost 127.0.0.2:80> DocumentRoot d:/abcd ServerName 127.0.0.2:80</VirtualHost> &l ...