优化Java堆大小5温馨提示

总结:Java没有足够的堆大小可能会导致性能非常大的影响,这无疑将给予必要的程序,并不能带来麻烦。本文总结了影响Java居前五位的能力不足,并整齐地叠优化?

笔者Pierre有一个10高级系统架构师有多年经验,他的主要专业领域是Java EE、中间件和JVM技术。依据他多年的工作实践经验,他发现很多性能问题都是由Java堆容量不足和调优引起的。

以下他将和大家分享很有用的5个Java堆优化技巧。

1.JVM:对难以理解的东西产生恐惧感

千万不要以为,通过配置,调优。就能够排除那些你所不明确的问题。

有些人觉得Java程序猿不需要知道内部JVM内存管理。

毫无疑问,这样的观点明显是错误的,假设想拓宽知识面和提升排除故障能力。你就必需要了解和学习一下JVM内存管理。

对于Java或者是Java EE新手来说,Java Heap调优和故障排除是一项很有挑战的工作。

以下会提供一些典型的案例场景:

client环境面临着有规律的OutOfMemoryError错误而且对业务造成了非常大的影响。

你的开发团队要在如此大的压力下去解决问题。一般会怎么做?

  1. 用谷歌搜索引擎找到类似的问题而且你会相信(或如果)你也面临相同的问题。

  2. 你会抓住JVM-Xms和存在OutOfMemoryError异常这几个keyword的样例,然后希望通过这种案例来高速解决client问题。
  3. 最后你会在你环境中使用相同的调优方法。

    两天后,问题仍然发生(甚至更糟或者略微好点)……

究竟是哪里错了呢?

首先。没有摸清问题根源所在?对开发环境没有正确地进行深层面(规格、负载情况等)理解。网络搜索是一个很优秀的学习方法和知识分享工具。可是你必须结合自己的实际项目。从根本上进行分析解决。

可能缺乏主要的JVM和JVM内存管理技能,阻止你把全部的点给连接起来。

今天讲的第一条技巧是帮助你理解主要的JVM原则及其与众不同的内存空间。

这些知识都是相当重要的。它能够帮助你做出有效的调优策略、更加正确合理的预測将来会产生的影响、提前知道未来须要做哪些调优工作。

以下来看一下JVM參考指南:

JVM内存分为3个内存空间

  • Java Heap:适用于全部的JVM厂商,通经常使用来拆分YoungGen(幼苗)和OldGen(终身享用)空间。

  • PermGen(永久代):适用于Sun HotSpot VM((PermGen空间在Java7或者Java8更新中将会被删除)
  • Native Heap(C-Heap):适用于全部的JVM厂商。

建议把以下的文章都能看一遍,最好把Sun的Java内存管理白皮书和OpenJDKS实现下载下来并细致阅读。

正如你所示,JVM内存管理比使用Xmx设置最大值更为复杂。

你须要查看每一个角度,包含本地和PermGen需求以及从主机上查看物理内存可用性(CPU core)。

在较大的Java Heap和较小的本地Heap比赛中。32位虚拟机可能会变得相当棘手。

试图在一个32位VM如2.5GB+上设置一个大型堆。依据应用程序占用和线程数量等因素会添加OutOfMemoryError这个异常抛出。64位JVM能够解决问题,但物理资源可用性和垃圾回收成本仍然是有限制的(成本主要集中在GC大小收集上)。

最大并不表示是最好的,所以请不要如果在一个16GB的64位虚拟机上能够执行20个Java EE应用程序。

2.数据和应用程序为王:回想静态占用需求

应用程序以及相关数据将决定Java堆空间占用需求。

通过静态内存,可“预測”以下的内存需求:

  • 确定将会有多少不同的应用程序部署到预先计划的一个单独的JVM进程上,比如有多少个ear文件、war文件、jar文件等。在一个JVM上部署的应用程序越多,对本机堆的需求就越多。
  • 确定有多少个类须要在执行时载入:包含第三方API。

    越多的类载入器和类在执行时被载入,在HotSpot VM PermGen空间和内部JIT相关优化对象上的需求就越高。

  • 确定数据缓存占用。如应用程序载入内部缓存数据结构(和第三方API),比如数据库中的数据缓存,从文件里读取数据等。数据缓存使用越多,Java Heap OldGen空间需求就越高。
  • 确定同意建立的中间件线程数量。这是很重要的,由于Java线程须要足够的本机内存。否则会抛OutOfMemoryError异常。

在JVM进程上部署的应用程序越多,对本地内存和PermGen空间的要求就越高。数据缓存并非序列化为一个磁盘或数据库,它将从OldGen空间里面须要额外的内存。

设法对静态内存占用进行合理的评估,在真正进行数据測试之前,设置一些JVM能力起点是很实用的。

对于32位JVM,通常不推荐一个Java堆大小超过2 GB(-Xms2048m,-Xmx2048m),对于Java EE应用程序和线程来说这样将须要足够的内存和本机堆PermGen。

这个评估是非常重要由于太多的应用程序部署在一个32位JVM进程上非常easy导致本机堆耗尽;尤其是在多重线程环境。

对于64位JVM。 一个3GB或者4GB的Java堆/JVM进程是推荐的起点。

3.业务流量设置规则:审查动态内存占用需求

业务流量一般会决定动态内存占用。通过观察各种监控工具能够发现并发用户与请求生成的JVM GC“心跳”。这是因为频繁的创建和垃圾回收短期或者长期对象。

一个典型的32位JVM,Java堆大小设置在2 GB(使用分代&并发收集器)通常为500 MB YoungGen分配空间和1.5 GB的OldGen空间。

最大限度地降低重大GC收集的频率是获得最佳性能的关键因素,所以在高峰的时候理解和评估须要多少内存是很重要的。

再次声明,应用程序类型和数据将决定内存需求。购物车的应用程序类型(长期居住的对象)涉及大型和非序列化会话数据,这个通常须要大型Java堆和非常多OldGen空间。

无状态和XML处理(非常多短命的对象)繁重的应用程序须要适当YoungGen空间。以尽量降低频率主要集合。

比如:

你有5个ear应用程序(2000多个Java类)要部署(包括中间件代码)

  1. 本地堆需求预计为1GB(必须足够大以处理线程创建等等。)PermGen空间大约是512 MB。
  2. 内部静态缓存大约500MB
  3. 在高峰时间。总预測流量是5000个并发用户
  4. 每一个用户的会话数据大约500K
  5. 在高峰期间,总流量会话要求是2.5GB。

正如你所示一样,在如此情况下,32位JVM进程就无法满足。

一个典型的解决方式是进行流量拆分,在几个JVM进程或物理主机(如果有足够的硬件和CPU core可用)上。

大多数时候,业务流量将推动内存占用。

除非你须要大量的数据缓存来实现适当的性能,典型的门户应用站点(媒体)繁重的应用程序需求。数据缓存太多的时候应该用一个黄色的标志标注一下。最好早点去又一次审视一下一些设计元素。

4.量体裁衣

这一条,你应该做到:

  1. 理解主要的JVM原则和内存空间。
  2. 对全部应用程序有深入的了解及其他们的特点(大小、类型、动态流量、无状态对象VS有状态对象、内部内存缓存等)。

  3. 对预測业务流量(并发用户)给每个应用程序能提出非常好的观点—假设你须要一个64位的虚拟内存,那么将设置哪个作为開始。

假设须要多个JVM(中间件)过程。

等一下。这样做并不足够。尽管上面的信息是至关重要的,而且关于Java堆的设置进行了“最佳推測”。相应用程序的行为进行模拟而且进行适当的分析、负载和性能測试来验证Java堆内存要求。

推荐Jprofiler工具给大家,学习怎样使用一个分析器的最好方法是正确理解应用程序的内存占用。还有一个方法是使用Eclipse MAT工具依据现有的环境进行堆转储分析。

堆转储很强大,它能够同意你查看和理解Java堆的整个内存占用,包括类载入器相关数据和在内存占用分析中必需要做的,特别是内存泄漏。

Java分析器和堆转储分析工具同意你理解和验证应用程序内存足迹。包括内存泄漏的检測和解决方式。

负载測试和性能測试是不可缺少的,通过模拟并发用户来验证早期评估是否正确,它也会把应用程序瓶颈暴露出来而且同意你进行微调。推荐一个很easy上手的工具:Apache Jmeter。

最后将看一下这种情况。应用程序在Java EE环境很正常,直到有一天全然正常的设备启动失败,比如硬件问题。

突然的环境执行能力下降和总体环境下降,究竟发生了什么?

引起“多米诺效应”的原因有非常多,但缺少JVM调优和处理故障转移的能力(短期额外负荷)是非经常见的。

假设JVM进程执行在80% + OldGen空间容量和频繁的垃圾收集,你怎样预期故障转移场景?

前面模拟的负载和性能測试应该模拟这种场景,调整你的调优设置使您的Java堆有足够的缓冲来处理额外的负载(额外的对象)在短期内。

这主要适用于动态内存占用,因为故障转移意味着将重定向一些固定的并发用户给可利用的JVM进程(中间件实例)。

5.分而治之

这一条的前提是你已经完毕了几十个负载測试。JVM已经不存在泄露,你的应用程序内存不能再进行不论什么降低。你已经尝试了几个调优策略。比如使用一个64位的Java堆空间在10GB以上。多个GC策略,虽然这样,仍然没有找到合适的能够接受的性能水平?

与当前的JVM规范相比。适当的垂直和水平伸缩。包含在每一个物理主机和跨多个主机上建立JVM进程来满足整个吞吐量和容量。假设在几个逻辑仓、自身的JVM进程、线程和调优值里打破应用程序列表那么IT环境的容错能力将更强大。

“分而治之”策略包含拆分应用程序流量到多个JVM进程,以下提供一些拆分技巧:

  1. 降低每一个JVM进程的Java堆大小(静态和动态的占用)
  2. 降低JVM调优复杂度。
  3. 降低GC流失和暂停每一个JVM进程
  4. 添加冗余和故障切换功能
  5. 排列最新的Cloud和IT虚拟化战略

当你发现已经花费了大量的时间在64位JVM进程调优上,是时候该好好审视一下你的中间件和JVM部署策略而且利用垂直和水平缩放。这条策略的许多认识需要支持其他硬件,但是从长远来看,。这是非常有效的,故意的。(章卢南/编)

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-08-27 23:47:00

优化Java堆大小5温馨提示的相关文章

优化Java堆大小的5个技巧

本文作者Pierre是一名有10多年经验的高级系统架构师,他的主要专业领域是Java EE.中间件和JVM技术.根据他多年的工作实践经验,他发现许多性能问题都是由Java堆容量不足和调优引起的.下面他将和大家分享非常实用的5个Java堆优化技巧. 1.JVM:对难以理解的东西产生恐惧感 千万不要以为,通过配置,调优,就可以排除那些你所不明白的问题.有些人认为Java程序员不需要知道内部JVM内存管理.毫无疑问,这种观点明显是错误的,如果想拓宽知识面和提升排除故障能力,你就必须要了解和学习一下JV

一步步优化JVM四:决定Java堆的大小以及内存占用

原文:http://blog.csdn.net/zhoutao198712/article/details/7783070 到目前为止,还没有做明确的优化工作.只是做了初始化选择工作,比如说:JVM部署模型.JVM运行环境.收集哪些垃圾回收器的信息以及需要遵守垃圾回收原则.这一步将介绍如何评估应用需要的内存大小以及Java堆大小.首先需要判断出应用存活的数据的大小,存活数据的大小是决定配置应用需要的Java堆大小的重要条件,也能够决定是否需要重新审视一下应用的内存需求或者修改应用程序以满足内存需

源码分析:Java堆的创建

虚拟机在内存中申请一片区域,由虚拟机自动管理,用来满足应用程序对象分配的空间需求,即堆空间. 由于程序运行的局部特性,程序创建的大多数对象都具有非常短的生命周期,而程序也会创建一些生命周期特别长的对象.简单的复制收集器无论对象的 生命周期是长是短,都会进行复制操作.而生命周期较长的对象在多次垃圾回收期间内并不会被回收,这就使得这些对象被来回复制而使得算法性能大大下降. 分代收集把堆分为多个子堆,分别用来存放不同寿命的对象.新生对象空间的将经历最频繁的垃圾回收,而对于经历了若干次垃圾收集后仍然存活

Dalvik虚拟机Java堆创建过程分析

使用C/C++开发应用程序最令头痛的问题就是内存管理.慎不留神,要么内存泄漏,要么内存破坏.虚拟机要解决的问题之一就是帮助应用程序自动分配和释放内存.为了达到这个目的,虚拟机在启动的时候向操作系统申请一大块内存当作对象堆.之后当应用程序创建对象时,虚拟机就会在堆上分配合适的内存块.而当对象不再使用时,虚拟机就会将它占用的内存块归还给堆.Dalvik虚拟机也不例外,本文就分析它的Java堆创建过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 从前面Da

JVM系列之二:JVM堆大小的建议

JVM的堆大小设置是一趟很深的水,既要有对架构高度认识和落地,也要有对语言内部机制深入理解和掌握. 首先,需要对JVM的Heap大小有一个预设和监测,见这篇文章选择合适Java堆大小的五个建议(5 Tips for Proper Java Heap Size),其实文中主要普及了一些JVM设置基础知识,强调需要了解的几个知识点和一般经验,也没有给出实战中具体可行的操作办法,其实每个系统是不一样的,就象病人因人而异一样,需要根据自己的系统和自己的经济条件能力找出适合自己的Heap大小. 堆主要分年

如何优化Java垃圾回收-zz

为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或行为: 已经通过 -Xms 和–Xmx 设置了内存大小 包含了 -server 参数 系统中没有超时日志等错误日志 换句话说,如果你没有设定内存的大小,并且系统充斥着大量的超时日志时,你就需要在你的系统中进行GC优化了. 但是,你需要时刻铭记一条:GC优化永远是最后一项任务. 你应该考虑一下进行GC

从 Java 代码到 Java 堆

本文将为您提供 Java? 代码内存使用情况的深入见解,包括将 int 值置入一个 Integer 对象的内存开销.对象委托的成本和不同集合类型的内存效率.您将了解到如何确定应用程序中的哪些位置效率低下,以及如何选择正确的集合来改进您的代码. 优化应用程序代码的内存使用并不是一个新主题,但是人们通常并没有很好地理解这个主题.本文将简要介绍 Java 进程的内存使用,随后深入探讨您编写的 Java 代码的内存使用.最后,本文将展示提高代码内存效率的方法,特别强调了 HashMap 和 ArrayL

Java堆内存不足

1)使用IDEA开发程序时有时候会提示“Java Heap space error”,说明IDEA默认配置的Java堆内存不足,程序需要更多的堆内存. 2)堆(Heap)和非堆(Non-heap)内存     按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”.可以看出JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码

关于java堆内存溢出的几种情况(转)

[情况一]: java.lang.OutOfMemoryError: Java heap space:这种是java堆内存不够,一个原因是真不够,另一个原因是程序中有死循环: 如果是java堆内存不够的话,可以通过调整JVM下面的配置来解决: <jvm-arg>-Xms3062m</jvm-arg> <jvm-arg>-Xmx3062m</jvm-arg> [情况二] java.lang.OutOfMemoryError: GC overhead limit