为了理解这个错误,我们先回顾一下操作系统相关的基础知识。我们知道,操作系统(operatingsystem)构建在进程(process)的基础上.进程由内核作业(kerneljobs)进行调度和维护,其中有一个内核作业称为“Outofmemorykiller(OOM终结者)”,与本节所讲的OutOfMemoryError有关。Outofmemorykiller在可用内存极低的情况下会杀死某些进程。只要达到触发条件就会激活,选中某个进程并杀掉。通常采用启发式算法,对所有进程计算评分(heuristicsscoring),得分最低的进程将被kill掉。因此Outofmemory:Killproce
Java平台限制了数组的最大长度。各个版本的具体限制可能稍有不同,但范围都在1~21亿之间。如果程序抛出java.lang.OutOfMemoryError:RequestedarraysizeexceedsVMlimit错误,就说明想要创建的数组长度超过限制。原因分析这个错误是由JVM中的本地代码抛出的.在真正为数组分配内存之前,JVM会执行一项检查:要分配的数据结构在该平台是否可以寻址(addressable).当然,这个错误比你所想的还要少见得多。一般很少看到这个错误,因为Java使用int类型作为数组的下标(index,索引)。在Java中,int类型的最大值为2^31–1=2,147
JVM启动参数指定了最大内存限制。如-Xmx以及相关的其他启动参数.假若JVM使用的内存总量超过可用的物理内存,操作系统就会用到虚拟内存。错误信息java.lang.OutOfMemoryError:Outofswapspace?表明,交换空间(swapspace,虚拟内存)不足,是由于物理内存和交换空间都不足所以导致内存分配失败。原因分析如果nativeheap内存耗尽,内存分配时,JVM就会抛出java.lang.OutOfmemoryError:Outofswapspace?错误消息,这个消息告诉用户,请求分配内存的操作失败了。Java进程使用了虚拟内存才会发生这个错误。对Java的垃圾
Java程序本质上是多线程的,可以同时执行多项任务。类似于在播放视频的时候,可以拖放窗口中的内容,却不需要暂停视频播放,即便是物理机上只有一个CPU。线程(thread)可以看作是干活的工人(workers)。如果只有一个工人,在同一时间就只能执行一项任务.假若有很多工人,那么就可以同时执行多项任务。和现实世界类似,JVM中的线程也需要内存空间来执行自己的任务.如果线程数量太多,就会引入新的问题:java.lang.OutOfMemoryError:Unabletocreatenewnativethread错误表达的意思是:程序创建的线程数量已达到上限值原因分析JVM向操作系统申请创建新的na
JVM限制了Java程序的最大内存,修改/指定启动参数可以改变这种限制。Java将堆内存划分为多个部分,如下图所示:【Java8及以上】这些内存池的最大值,由-Xmx和-XX:MaxMetaspaceSize等JVM启动参数指定.如果没有明确指定,则根据平台类型(OS版本+JVM版本)和物理内存的大小来确定。java.lang.OutOfMemoryError:Metaspace错误所表达的信息是:元数据区(Metaspace)已被用满原因分析如果你是Java老司机,应该对PermGen比较熟悉.但从Java8开始,内存结构发生重大改变,不再使用Permgen,而是引入一个新的空间:Metas
说明:Permgen(永久代)属于JDK1.7及之前版本的概念;为了适应Java程序的发展,JDK8以后的版本采用限制更少的MetaSpace来代替,详情请参考下一篇文章:OutOfMemoryError系列(4):Metaspace。JVM限制了Java程序的最大内存使用量,可以通过启动参数来配置。而Java的堆内存被划分为多个区域,如下图所示:这些区域的最大值,由JVM启动参数-Xmx和-XX:MaxPermSize指定.如果没有明确指定,则根据操作系统平台和物理内存的大小来确定。java.lang.OutOfMemoryError:PermGenspace错误信息所表达的意思是:永久代(
Java运行时环境内置了垃圾收集(GC)模块.上一代的很多编程语言中并没有自动内存回收机制,需要程序员手工编写代码来进行内存分配和释放,以重复利用堆内存。在Java程序中,只需要关心内存分配就行。如果某块内存不再使用,垃圾收集(GarbageCollection)模块会自动执行清理。GC的详细原理请参考GC性能优化系列文章,一般来说,JVM内置的垃圾收集算法就能够应对绝大多数的业务场景。java.lang.OutOfMemoryError:GCoverheadlimitexceeded这种情况发生的原因是,程序基本上耗尽了所有的可用内存,GC也清理不了。原因分析JVM抛出java.lang.O
每个Java程序都只能使用一定量的内存,这种限制是由JVM的启动参数决定的。而更复杂的情况在于,Java程序的内存分为两部分:堆内存(Heapspace)和永久代(PermanentGeneration,简称Permgen):这两个区域的最大内存大小,由JVM启动参数-Xmx和-XX:MaxPermSize指定.如果没有明确指定,则根据平台类型(OS版本+JVM版本)和物理内存的大小来确定。假如在创建新的对象时,堆内存中的空间不足以存放新创建的对象,就会引发java.lang.OutOfMemoryError:Javaheapspace错误。不管机器上还没有空闲的物理内存,只要堆内存使用量达到
本章介绍导致GC性能问题的典型情况。相关示例都来源于生产环境,为演示需要做了一定程度的精简。说明:AllocationRate,翻译为分配速率,而不是分配率;因为不是百分比,而是单位时间内分配的量;同理,PromotionRate翻译为提升速率;高分配速率(HighAllocationRate)分配速率(Allocationrate)表示单位时间内分配的内存量。通常使用MB/sec作为单位,也可以使用PB/year等。分配速率过高就会严重影响程序的性能。在JVM中会导致巨大的GC开销。如何测量分配速率?指定JVM参数:-XX:+PrintGCDetails-XX:+PrintGCTimeSta
进行GC性能调优时,需要明确了解,当前的GC行为对系统和用户有多大的影响。有多种监控GC的工具和方法,本章将逐一介绍常用的工具。JVM在程序执行的过程中,提供了GC行为的原生数据。那么,我们就可以利用这些原生数据来生成各种报告。原生数据(rawdata)包括:各个内存池的当前使用情况,各个内存池的总容量,每次GC暂停的持续时间,GC暂停在各个阶段的持续时间。可以通过这些数据算出各种指标,例如:程序的内存分配率,提升率等等。本章主要介绍如何获取原生数据。后续的章节将对重要的派生指标(derivedmetrics)展开讨论,并引入GC性能相关的话题。JMXAPI从JVM运行时获取GC行为数据,最简
说明:Capacity:性能,能力,系统容量;文中翻译为"系统容量";意为硬件配置和并发服务能力。GC调优(TuningGarbageCollection)和其他性能调优是同样的原理。初学者可能会被200多个GC参数弄得一头雾水,然后随便调整几个来试试结果,又或者修改几行代码来测试。其实只要参照下面的步骤,就能保证你的调优方向正确:列出性能调优指标(Stateyourperformancegoals)执行测试(Runtests)检查结果(Measuretheresults)与目标进行对比(Comparetheresultswiththegoals)如果达不到指标,修改配置参
学习了GC算法的相关概念之后,我们将介绍在JVM中这些算法的具体实现。首先要记住的是,大多数JVM都需要使用两种不同的GC算法——一种用来清理年轻代,另一种用来清理老年代。我们可以选择JVM内置的各种算法。如果不通过参数明确指定垃圾收集算法,则会使用宿主平台的默认实现。本章会详细介绍各种算法的实现原理。下面是关于Java8中各种组合的垃圾收集器概要列表,对于之前的Java版本来说,可用组合会有一些不同:YoungTenuredJVMoptionsIncremental(增量GC)Incremental-XincgcSerialSerial-XX:+UseSerialGCParallelScav
相关术语翻译说明:Mark,标记;Sweep,清除;Compact,整理;也有人翻译为压缩,译者认为GC时不存在压缩这回事。Copy,复制;copy用作名词时一般翻译为拷贝/副本,用作动词时翻译为复制。注:《垃圾回收算法手册》将MarkandSweep翻译为:标记-清扫算法;译者认为标记-清除更容易理解。本章简要介绍GC的基本原理和相关技术,下一章节再详细讲解GC算法的具体实现。各种垃圾收集器的实现细节虽然并不相同,但总体而言,垃圾收集器都专注于两件事情:查找所有存活对象抛弃其他的部分,即死对象,不再使用的对象。第一步,记录(census)所有的存活对象,在垃圾收集中有一个叫做标记(Marki
标记-清除(MarkandSweep)是最经典的垃圾收集算法。将理论用于生产实践时,会有很多需要优化调整的地点,以适应具体环境。下面通过一个简单的例子,让我们一步步记录下来,看看如何才能保证JVM能安全持续地分配对象。碎片整理(FragmentingandCompacting)每次执行清除(sweeping),JVM都必须保证不可达对象占用的内存能被回收重用。但这(最终)有可能会产生内存碎片(类似于磁盘碎片),进而引发两个问题:写入操作越来越耗时,因为寻找一块足够大的空闲内存会变得非常麻烦。在创建新对象时,JVM在连续的块中分配内存。如果碎片问题很严重,直至没有空闲片段能存放下新创建的对象,就
说明:在本文中,GarbageCollection翻译为“垃圾收集”,garbagecollector翻译为“垃圾收集器”;一般认为,垃圾回收和垃圾收集是同义词。MinorGC翻译为:小型GC;而不是次要GCMajorGC翻译为:大型GC;而不是主要GC原因在于,大部分情况下,发生在年轻代的MinorGC次数会很多,翻译为次要GC明显不对。FullGC翻译为:完全GC;为了清晰起见,一般直接译为FullGC,读者明白即可;其中大型GC和完全GC差不多,这些术语出自官方的各种分析工具和垃圾收集日志。并不是很统一。1.垃圾收集简介顾名思义,垃圾收集(GarbageCollection)的意思就是—