您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
深入理解JVM之内存区域与内存溢出
 
来源:wustrive's blog 发布于 2016-11-2
   次浏览      
 

文章目录

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

1.1. 运行时数据区域

1.1.1. 程序计数器

1.1.2. java虚拟机栈

1.1.3. 本地方法栈

1.1.4. Java堆(Java Heap)

1.1.5. 方法区

1.1.6. 运行时常量池

1.1.7. 直接内存

1.2. HotSpot虚拟机

1.2.1. 对象的创建

1.2.2. 对象的访问定位

1.3. OOM异常的解决思路

1.4. 参考

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

运行时数据区域

深入理解jvm之内存区域与内存溢出

程序计数器

当前线程所执行的字节码的行号指示器

当前线程私有

不会出现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异常示例:

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微服务新生代之Nacos
深入理解Java中的容器
Java容器详解
Java代码质量检查工具及使用案例
相关文档

Java性能优化
Spring框架
SSM框架简单简绍
从零开始学java编程经典
相关课程

高性能Java编程与系统性能优化
JavaEE架构、 设计模式及性能调优
Java编程基础到应用开发
JAVA虚拟机原理剖析
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

Java 中的中文编码问题
Java基础知识的三十个经典问答
玩转 Java Web 应用开发
使用Spring更好地处理Struts
用Eclipse开发iPhone Web应用
插件系统框架分析
更多...   

Struts+Spring+Hibernate
基于J2EE的Web 2.0应用开发
J2EE设计模式和性能调优
Java EE 5企业级架构设计
Java单元测试方法与技术
Java编程方法与技术

Struts+Spring+Hibernate/EJB+性能优化
华夏基金 ActiveMQ 原理与管理
某民航公司 Java基础编程到应用开发
某风电公司 Java 应用开发平台与迁移
日照港 J2EE应用开发技术框架与实践
某跨国公司 工作流管理JBPM
东方航空公司 高级J2EE及其前沿技术
更多...