- 浏览: 1428187 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (363)
- oracle (43)
- 缓存策略 (4)
- 数据库设计 (7)
- IntelliJ IDEA (8)
- freemarker (3)
- JSP (12)
- java基础 (75)
- tomcat (14)
- 服务器 (10)
- maven (3)
- linux (21)
- e-learning (2)
- 手机开发 (1)
- 设计模式 (6)
- 技术之外 (2)
- 工具的使用 (8)
- HTML 5 (5)
- 网站前台 (38)
- 网站后台 (11)
- 项目管理 (12)
- 面试题 (5)
- 幽默 (0)
- 系统架构 (8)
- 创业 (10)
- div-css (5)
- 诗词歌赋 (1)
- 网络课堂组知识库 (4)
- 杂家 (3)
- android (12)
- 框架 (14)
- 读书笔记 (1)
- 孙子兵法 (1)
- mysql (3)
- 小人书 (0)
- Jquery (6)
- eclipse (2)
- 正则表达式 (1)
最新评论
-
a98709474:
写的很详细,看完了,明白了这种概念了
数据库水平切分(拆库拆表)的实现原理解析(转) -
a98709474:
MYSQL分库分表总结 -
CatchU:
7年前的招聘要求,厉害厉害
面试要求 -
luozhixiong:
<table class="bbcode&qu ...
MYSQL分库分表总结 -
沈寅麟:
好用
freemarker格式化
OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:
1:是排查程序是否有BUG导致内存泄漏;
2:是调整JVM启动参数增大内存。
OutOfMemoryError有好几种情况,每次遇到这个错误时,观察OutOfMemoryError后面的提示信息,就可以发现不同之处,如:
虽然都叫OutOfMemoryError,但每种错误背后的成因是不一样的,解决方法也要视情况而定,不能一概而论。只有深入了解JVM的内存结构并仔细分析错误信息,才有可能做到对症下药,手到病除。
JVM规范JVM规范对Java运行时的内存划定了几块区域,有:
但对各块区域的内存布局和地址空间却没有明确规定,而留给各JVM厂商发挥的空间。
HotSpot JVMSun自家的HotSpot JVM实现对堆内存结构有相对明确的说明。按照HotSpot JVM的实现:
堆内存分为3个代:
众所周知,GC(垃圾收集)就是发生在堆内存这三个代上面的。Young用于分配新的Java对象,其又被分为三个部分:Eden Space和两块Survivor Space(称为From和To),Old用于存放在GC过程中从Young Gen中存活下来的对象,Permanent用于存放JVM加载的class等元数据。详情参见HotSpot内存管理白皮书。堆的布局图示如下:
根据这些信息,我们可以推导出JVM规范的内存分区和HotSpot实现中内存区域的对应关系:JVM规范的Heap对应到Young和Old Generation,方法区和常量池对应到Permanent Generation。对于Stack内存,HotSpot实现也没有详细说明,但HotSpot白皮书上提到,Java线程栈是用宿主操作系统的栈和线程模型来表示的,Java方法和native方法共享相同的栈。因此,可以认为在HotSpot中,JVM栈和本地方法栈是一回事。
经过上述铺垫,可以得知,JVM进程的内存大致分为Heap空间和Stack空间两部分。Heap又分为Young、Old(Tenured)、Permanent三个代。Stack分为Java方法栈和native方法栈(不做区分),在Stack内存区中,可以创建多个线程栈,每个线程栈占据Stack区中一小部分内存,线程栈是一个LIFO数据结构,每调用一个方法,会在栈顶创建一个Frame,方法返回时,相应的Frame会从栈顶移除(通过移动栈顶指针)。在这每一部分内存中,都有可能会出现溢出错误。回到开头的OutOfMemoryError,下面逐个说明错误原因和解决方法(每个OutOfMemoryError都有可能是程序BUG导致,因此解决方法不包括对BUG的排查)。
java.lang.OutOfMemoryError: Java heap space
原因:Heap内存溢出,意味着Young和Old generation的内存不够。
解决:调整java启动参数 -Xms -Xmx 来增加Heap内存。
java.lang.OutOfMemoryError: unable to create new native thread
原因:Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。
解决:由于JVM没有提供参数设置总的stack空间大小,但可以设置单个线程栈的大小;而系统的用户空间一共是3G,除了Text/Data/BSS/MemoryMapping几个段之外,Heap和Stack空间的总量有限,是此消彼长的。因此遇到这个错误,可以通过两个途径解决:
java.lang.OutOfMemoryError: PermGen space
原因:Permanent Generation空间不足,不能加载额外的类。
解决:调整-XX:PermSize= -XX:MaxPermSize= 两个参数来增大PermGen内存。一般情况下,这两个参数不要手动设置,只要设置-Xmx足够大即可,JVM会自行选择合适的PermGen大小。对于spring,hibernate这些需要动态类型支持的框架,这个区域需要足够的空间。
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:这个错误比较少见(试着new一个长度1亿的数组看看),同样是由于Heap空间不足。如果需要new一个如此之大的数组,程序逻辑多半是不合理的。
解决:修改程序逻辑吧。或者也可以通过-Xmx来增大堆内存。
在GC花费了大量时间,却仅回收了少量内存时,也会报出OutOfMemoryError,我只遇到过一两次。当使用-XX:+UseParallelGC或-XX:+UseConcMarkSweepGC收集器时,在上述情况下会报错,在HotSpot GC Turning文档上有说明:
The parallel(concurrent) collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown.
对这个问题,一是需要进行GC turning,二是需要优化程序逻辑。
java.lang.StackOverflowError
原因:这也内存溢出错误的一种,即线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小。
解决:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小。
JVM中堆被分为了3个大的区间,同时JVM也提供了一些选项对Young,Tenured的大小进行控制。
-Xms :指定了JVM初始启动以后初始化内存
-Xmn :参数设置了年轻代的大小
-Xmx:指定JVM堆得最大内存,在JVM启动以后,会分配-Xmx参数指定大小的内存给JVM,但是不一定全部使用,JVM会根据-Xms参数来调节真正用于JVM的内存
-XX:NewRatio=8意味着tenured 和 young的比值8:1,这样eden+2*survivor=1/9
-XX:SurvivorRatio=32意味着eden和一个survivor的比值是32:1,这样一个Survivor就占Young区的1/34.
-XX:PermSize=16M -XX:MaxPermSize=64M
Thread Stack
-XX:Xss=128K
1:是排查程序是否有BUG导致内存泄漏;
2:是调整JVM启动参数增大内存。
OutOfMemoryError有好几种情况,每次遇到这个错误时,观察OutOfMemoryError后面的提示信息,就可以发现不同之处,如:
引用
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: unable to create new native thread
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
java.lang.OutOfMemoryError: unable to create new native thread
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
虽然都叫OutOfMemoryError,但每种错误背后的成因是不一样的,解决方法也要视情况而定,不能一概而论。只有深入了解JVM的内存结构并仔细分析错误信息,才有可能做到对症下药,手到病除。
JVM规范JVM规范对Java运行时的内存划定了几块区域,有:
- JVM栈(Java Virtual Machine Stacks)、
- 堆(Heap)、
- 方法区(Method Area)、
- 常量池(Runtime Constant Pool)、
- 本地方法栈(Native Method Stacks),
但对各块区域的内存布局和地址空间却没有明确规定,而留给各JVM厂商发挥的空间。
HotSpot JVMSun自家的HotSpot JVM实现对堆内存结构有相对明确的说明。按照HotSpot JVM的实现:
堆内存分为3个代:
- Young Generation、
- Old(Tenured) Generation、
- Permanent Generation。
众所周知,GC(垃圾收集)就是发生在堆内存这三个代上面的。Young用于分配新的Java对象,其又被分为三个部分:Eden Space和两块Survivor Space(称为From和To),Old用于存放在GC过程中从Young Gen中存活下来的对象,Permanent用于存放JVM加载的class等元数据。详情参见HotSpot内存管理白皮书。堆的布局图示如下:
根据这些信息,我们可以推导出JVM规范的内存分区和HotSpot实现中内存区域的对应关系:JVM规范的Heap对应到Young和Old Generation,方法区和常量池对应到Permanent Generation。对于Stack内存,HotSpot实现也没有详细说明,但HotSpot白皮书上提到,Java线程栈是用宿主操作系统的栈和线程模型来表示的,Java方法和native方法共享相同的栈。因此,可以认为在HotSpot中,JVM栈和本地方法栈是一回事。
经过上述铺垫,可以得知,JVM进程的内存大致分为Heap空间和Stack空间两部分。Heap又分为Young、Old(Tenured)、Permanent三个代。Stack分为Java方法栈和native方法栈(不做区分),在Stack内存区中,可以创建多个线程栈,每个线程栈占据Stack区中一小部分内存,线程栈是一个LIFO数据结构,每调用一个方法,会在栈顶创建一个Frame,方法返回时,相应的Frame会从栈顶移除(通过移动栈顶指针)。在这每一部分内存中,都有可能会出现溢出错误。回到开头的OutOfMemoryError,下面逐个说明错误原因和解决方法(每个OutOfMemoryError都有可能是程序BUG导致,因此解决方法不包括对BUG的排查)。
java.lang.OutOfMemoryError: Java heap space
原因:Heap内存溢出,意味着Young和Old generation的内存不够。
解决:调整java启动参数 -Xms -Xmx 来增加Heap内存。
java.lang.OutOfMemoryError: unable to create new native thread
原因:Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。
解决:由于JVM没有提供参数设置总的stack空间大小,但可以设置单个线程栈的大小;而系统的用户空间一共是3G,除了Text/Data/BSS/MemoryMapping几个段之外,Heap和Stack空间的总量有限,是此消彼长的。因此遇到这个错误,可以通过两个途径解决:
- 1.通过-Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError);
- 2.通过-Xms -Xmx 两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用)。
java.lang.OutOfMemoryError: PermGen space
原因:Permanent Generation空间不足,不能加载额外的类。
解决:调整-XX:PermSize= -XX:MaxPermSize= 两个参数来增大PermGen内存。一般情况下,这两个参数不要手动设置,只要设置-Xmx足够大即可,JVM会自行选择合适的PermGen大小。对于spring,hibernate这些需要动态类型支持的框架,这个区域需要足够的空间。
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:这个错误比较少见(试着new一个长度1亿的数组看看),同样是由于Heap空间不足。如果需要new一个如此之大的数组,程序逻辑多半是不合理的。
解决:修改程序逻辑吧。或者也可以通过-Xmx来增大堆内存。
在GC花费了大量时间,却仅回收了少量内存时,也会报出OutOfMemoryError,我只遇到过一两次。当使用-XX:+UseParallelGC或-XX:+UseConcMarkSweepGC收集器时,在上述情况下会报错,在HotSpot GC Turning文档上有说明:
The parallel(concurrent) collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown.
对这个问题,一是需要进行GC turning,二是需要优化程序逻辑。
java.lang.StackOverflowError
原因:这也内存溢出错误的一种,即线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小。
解决:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小。
JVM中堆被分为了3个大的区间,同时JVM也提供了一些选项对Young,Tenured的大小进行控制。
-Xms :指定了JVM初始启动以后初始化内存
-Xmn :参数设置了年轻代的大小
-Xmx:指定JVM堆得最大内存,在JVM启动以后,会分配-Xmx参数指定大小的内存给JVM,但是不一定全部使用,JVM会根据-Xms参数来调节真正用于JVM的内存
-XX:NewRatio=8意味着tenured 和 young的比值8:1,这样eden+2*survivor=1/9
-XX:SurvivorRatio=32意味着eden和一个survivor的比值是32:1,这样一个Survivor就占Young区的1/34.
-XX:PermSize=16M -XX:MaxPermSize=64M
Thread Stack
-XX:Xss=128K
发表评论
-
打印IP 来源
2014-10-16 22:07 934<% String userAgent = reques ... -
java 写文本换行
2014-08-08 18:34 1946import org.apache.commons.io.Fi ... -
DBCP连接池配置示例
2014-06-17 11:44 1238<bean id="dataSourceOra ... -
CGLIB与asm
2014-05-05 14:42 1338“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言 ... -
201404转成 2014.04
2014-03-31 17:45 980public static void main(Str ... -
取出 字符串中的 网址
2013-10-15 17:47 1253public static void main(Str ... -
java反国际化
2013-09-23 18:10 998public static String fromEn ... -
AtomicInteger与Volatile修饰
2013-02-05 11:50 6038今天写代码,尝试使用了AtomicInteger这个类,感觉 ... -
ExecutorService线程池
2013-02-05 11:40 1616http://blog.sina.com.cn/s/blog ... -
web.xml中load-on-startup的作用
2012-12-24 10:06 1656如下一段配置,熟悉DWR的再熟悉不过了: <servle ... -
最新版本
2012-09-13 09:28 1000Java SE 7u7 apache-tomcat-7.0. ... -
格式化数字
2012-09-10 20:12 899public static void main(Str ... -
用apache common io包获得文件扩展名
2012-09-09 23:11 1360apache common io包包含了很多非常实用的工具类, ... -
值传递,引用传递
2012-07-28 23:29 1132java 对于 8种基本类型 和 他们的包装类型 , 外 ... -
代码之丑
2012-07-07 22:01 2314原文:http://www.infoq.com/cn/news ... -
Memcache
2012-06-27 09:36 1037Memcache是一个高性能的分布式的内存对象缓存系统,通过在 ... -
ActiveMQ
2012-06-14 15:09 15148ActiveMQ 是Apache出品,最流行的,能力强劲的开源 ... -
proxool配置
2012-06-12 11:43 1176项目结构 所需jar包 proxool.prope ... -
各种文件的注释
2012-04-23 10:44 993<%-- comment --%> JSP注释,也称为“隐藏注 ... -
List排序
2012-03-27 20:18 1191集合类List存放的数据,默认是按照放入时的顺序存放的,比如依 ...
相关推荐
1. **JVM内存结构** JVM内存分为几个关键区域:方法区(Method Area)、堆(Heap)、栈(Stack)、程序计数器(PC Register)和本地方法栈(Native Method Stack)。每个区域都有特定的用途: - **方法区**:存储...
理解JVM内存结构和内存分配机制对于避免内存溢出(OutOfMemoryError)、提升程序性能、减少垃圾回收开销至关重要。开发者应关注内存配置、对象生命周期管理以及适当的垃圾回收策略,以优化应用程序的性能和稳定性。
### JVM内存空间分配详解 #### 一、JVM内存模型概览 ...综上所述,理解JVM内存分配机制对于Java开发者来说至关重要,这不仅有助于编写高效、稳定的代码,还能在遇到性能瓶颈时快速定位问题并进行优化。
在这份由Sun Microsystems公司出版的《JVM内存管理白皮书》中,我们可以找到关于Java虚拟机(JVM)内存管理的详细介绍和深入分析。这份文档对于想要深入了解JVM工作原理的读者来说是一份宝贵的学习资料。在这份...
1. **内存模型**:JVM内存分为堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、程序计数器(PC Register)和本地方法栈(Native Method Stack)。堆是存储对象实例的主要区域,栈则用于存储方法调用时的...
在进行JVM内存配置优化之前,我们需要了解Java虚拟机(JVM)的内存结构。Java的逻辑内存模型大致分为几个部分: 1. **堆内存(Heap)**:主要用于存储对象实例、数组等引用类型的数据。在Java中使用`new`关键字创建的...
在Java程序中,JVM内存是一个重要组成部分,它管理着对象的创建、存储和回收等过程。理解JVM内存分配对于编写高效的Java应用程序至关重要。 描述部分指出,本文将探讨JVM如何使用Windows和Linux平台上的本机内存。...
了解JVM内存结构和调优技术,可以帮助我们编写出更高效、更稳定的Java应用程序。在实际工作中,结合监控工具(如VisualVM、JConsole、JMX等)进行分析,可以更好地理解应用程序的内存行为并进行针对性优化。同时,...
- `java.lang.OutOfMemoryError: Java heap space`表示Java程序在运行过程中耗尽了所有可用的堆内存空间。 - 当程序创建新的对象或者分配内存时,如果无法在现有的堆内存中找到足够的连续空闲内存块,则会抛出此...
这类异常通常表明Java虚拟机(JVM)在运行过程中遇到了内存不足的问题,特别是当堆内存无法满足程序的需求时。 #### 二、原因分析 1. **项目规模过大**:如果项目中的类文件数量过多或者单个对象占用内存较大时,...
了解JVM内存区域的划分及其工作原理对于Java开发者来说至关重要,这有助于理解和解决性能问题,如内存泄漏和栈溢出。在实际开发中,合理设置JVM参数(如-Xms, -Xmx等)可以有效防止内存错误,同时,通过阅读如《深入...
了解JVM内存结构是理解内存溢出的关键。 #### 二、JVM运行时数据区域 - **程序计数器(Program Counter Register)**:当前线程所执行的字节码的行号指示器。每条线程拥有独立的程序计数器,因此它属于线程私有区域...
了解JVM内存结构有助于我们理解Java应用程序的内存分配和管理,从而进行更有效的内存优化,减少内存溢出和栈溢出等问题。例如,通过调整堆大小、优化对象生命周期、合理使用静态变量等策略,可以提高应用的性能和...
Java中的“内存不足OOM (Out Of Memory):java.lang.OutOfMemoryError”是一个常见的运行时错误,它表示Java虚拟机(JVM)在尝试分配新的对象或数据结构时,发现系统内存不足以完成此操作。这个问题通常发生在程序...
### Java内存模型与内存结构详解 #### 一、引言 在深入了解Java内存模型与内存结构之前,我们首先需要明确这两个概念的区别与联系。简单来说,“内存结构”侧重于描述虚拟机执行Java程序时如何组织内存空间;而...
1. **JVM内存结构**: JVM内存主要分为五个区域:方法区(Method Area)、堆(Heap)、虚拟机栈(Java Virtual Machine Stack)、本地方法栈(Native Method Stack)和程序计数器(Program Counter Register)。 2...
JVM内存区域划分是Java虚拟机(JVM)中的一种内存管理机制,主要分为五个部分:程序计数器、Java栈、本地方法栈、堆和方法区。这些区域各自扮演着不同的角色,共同组成了JVM的内存管理系统。 程序计数器 程序...
2. **内存管理**:JVM内存主要分为堆内存和栈内存,其中堆内存用于对象实例的存储,栈内存则处理方法调用。了解内存分配、GC(Garbage Collection)策略以及内存泄漏的检测和预防对于避免程序运行缓慢至关重要。 3....