《JVM》(五)内存溢出异常与调优

内存溢出异常

除了程序计数器之外,jvm的其他几个运行时区域都存在着OOM异常的可能性

java堆溢出

对象数量达到最大堆的容量限制后

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

线程请求的栈深度大于虚拟机所允许的最大深度

虚拟机在扩展栈时无法申请到足够的内存空间

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

生成大量的class的情况

JDK的可视化工具

JConsole:java监视与管理控制台

概述;类;vm摘要;MBean;

内存(相当于jstat);

线程(相当于jstack);

VisualVM:多合一故障处理工具

显示虚拟机进程以及进程的配置,环境信息(jps,jinfo)

监视应用程序的CPU,GC,堆,方法区以及线程的信息(jstat,jstack)

dump以及分析堆转储快照(jmap,jhat)

方法级的程序运行性能分析,找出被调用最多,运行时间最长的方法

离线程序快照

调优案例分析

1.高性能硬件上的程序部署策略

问题:将网站堆内存固定在12GB,网站不定期出现长时间失去响应的情况。

原因:失去响应是因为过大的堆内存,程序设计产生成批大对象,进入老年代,GC停顿导致的。

解决:给java虚拟机分配超大堆的前提是,把握程序的Full GC频率控制得足够低。

控制GC频率的关键是不能有成批的,长时间生存的大对象产生,这样才能保证老年代的稳定。

现阶段64位jdk性能测试结果普遍低于32位jdk,多数人选择使用若干个32位虚拟机建立逻辑集群:在一台物理机器上启动多个应用服务器进程,每个进程分配不同端口,在前端搭一个负载均衡器。

无session复制的亲和式集群:均衡器按照一定的算法(一般根据sessionId分配)将一个固定的用户请求永远分配到固定的一个集群节点处理。

2.集群间同步导致的内存溢出

问题:亲和式集群,节点间没有session同步,需要有一些数据共享,使用JBossCache构建一个全局缓存。不定期出现多次内存溢出问题

原因:JBossCache 的缺陷。JBossCache在发送数据时有一个全局filter,把数据操作时间同步到所有的节点中,当网络情况不满足,重发数据在内存中不断堆积

解决:需要被集群共享的数据,使用类似JBossCache的缓存框架同步时,可以读操作频繁,不能写频繁。

3.堆外内存导致的溢出错误

问题:GC并不频繁,Eden区,surviver区,老年代以及永久代均表示压力不大,但还是报错内存溢出

原因:除了java堆和永久代,还有些区域会占用一定的内存:Direct Memory;线程堆栈;socket缓冲区...

4.服务器jvm进程崩溃

问题:使用了异步方式调用另一个系统的web服务,速度不对等,导致等待的socket连接越来越多,虚拟机崩溃

解决:将异步调用改为生产者/消费者的消息队列实现

原文地址:http://blog.51cto.com/13580976/2148192

时间: 2024-10-08 19:29:59

《JVM》(五)内存溢出异常与调优的相关文章

如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习<深入理解java虚拟机-JVM高级特性与最佳实践>这本书,终于初步了解了一下java虚拟机的内存模型.本文通过写出使jvm发生内存溢出异常的代码来对自己的学习结果进行总结,同时也提醒自己以后写代码时候不要再跳进这个坑啦. java的内存管理是由java虚拟机自动进行管理的,并不需要程序员过多的手动干预

JVM学习与问题总结——java内存区域与内存溢出异常

java虚拟机将内存分为哪些区域? 根据Java SE7版本的Java虚拟机规范,虚拟机管理的内存包括5个运行时数据区域: 程序计数器 虚拟机栈 本地方法栈 方法区 堆 运行时数据区各部分的作用? 程序计数器 一个线程所执行的字节码的行号指示器. 字节码解释器会通过改变计数器的值来选取下一条将要执行的指令,那么分支.循环.跳转.异常处理.线程恢复都需要依赖计数器来完成.而Java虚拟机当中的多线程是通过争取CPU时间片来切换线程执行任务,当一个线程重新获取CPU时间片的时候就需要恢复上一次任务执

深入理解JVM读书笔记一: Java内存区域与内存溢出异常

Java虚拟机管理的内存包括几个运行时数据内存:方法区.虚拟机栈.本地方法栈.堆.程序计数器,其中方法区和堆是由线程共享的数据区,其他几个是线程隔离的数据区. 2.2 运行时数据区域 2.2.1程序计数器 程序计数器是一块较小的内存,他可以看做是当前线程所执行的行号指示器.字节码解释器工作的时候就是通过改变这个计数器的值来选取下一条需要执行的字节码的指令,分支.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成.如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚

JVM高级特性与实践(一):Java内存区域 与 内存溢出异常

对于从事C.C++的开发人员而言,在内存管理领域,他们具有绝对的“权利”——拥有每个对象的控制权,并担负着每个对象生命周期的维护责任.而对于Java开发人员而言,在虚拟机自动内存管理机制的帮助下,无需为每一个创建new操作去配对 delete/free 代码,减少内存泄漏和内存溢出的问题,这些都交给了Java虚拟机去进行内存控制,但是正因如此,当出现相关问题时,若不了解JVM使用内存规则,就难以排查错误.接下来以此篇文章记录学习Java虚拟机内存各个区域概念.作用.服务对象以及可能产生的问题.

Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)

转载自https://github.com/pzxwhc/MineKnowContainer/issues/25 包括:1. 栈溢出(StackOverflowError)2. 堆溢出(OutOfMemoryError:java heap space)3. 永久代溢出(OutOfMemoryError: PermGen space)4. OutOfMemoryError:unable to create native thread Java虚拟机规范规定JVM的内存分为了好几块,比如堆,栈,程序

JVM(三)-内存溢出OutOfMemoryError

一.内存溢出OutOfMemoryError (1)java堆溢出 ①Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常. 代码清单1中代码限制Java堆的大小为20MB,不可扩展(将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出

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

文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了开始.如果有什么错误或者遗漏,欢迎指出. 一.概述 先上一张图 这张图主要列出了Java虚拟机管理的内存的几个区域. 常有人把Java内存区分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分实际上远比这复杂,从上图就可以看出了.堆栈分法中所指的"栈"实际上只是虚拟机栈,或者说是虚拟机栈中的局部变量表部分.接下

Java虚拟机结构及常见内存溢出异常

每个Java虚拟机都有一个类加载器子系统,根据某个全限定名来装入类型,同样每个Java虚拟机都有一个执行引擎,它负责执行那些包含在被装载类的方法中的指令. 当虚拟机运行一个程序时,就需要从已加载的文件中得到信息,将这些信息组织到运行时数据区,以便于管理. Java运行时的数据区域划分 1.程序计数器:程序计数器是一块较小的内存空间,可以看做是当前线程的字节码的行号指示器. Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个时刻,一个处理器只会执行一条线程中的指

内存溢出异常

Java堆 存储对象实例,我们只要不断创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象达到最大堆容量限制后产生内存溢出异常. java.lang.OutOfMemoryError:Java heap space. 原因分析:确认内存中对象是否是必要的.也就是首先要分清楚到底是出现了内存泄露还是内存溢出. 内存映像分析工具,检查是否是内存泄露,还是内存溢出. 2.4.2 虚拟机栈和本地方法栈溢出 本地变量表.StackOverflowError异常.