`
crazier9527
  • 浏览: 1008712 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

JVM优化配置《一》

OOM这个缩写就是Java程序开发过程中让人最头痛的问题:Out of Memory。在很多开发人员的开发过程中,或多或少的都会遇到这类问题,这类问题定位比较困难,往往需要根据经验来判断可能出现问题的代码。原因主要是 两个:对象没有被释放(多种情况引起,往往是比较隐蔽的引用导致被Hold而无法被回收)。另一种就是真的Memory不够用了,需要增加JVM的 Heap来满足应用程序的需求。最近有同事发的关于解决OOM的问题,让我了解了原来OOM除了在JVM Heap不够时会发生,在Native Heap不够的时候也会发生,同时JVM Heap和Native Heap存在着相互影响和平衡的关系,因此就仔细的去看了关于OOM和JVM配置优化的内容。
OOM
       在 其他语言类似于C,Delphi等等由于内存都是由自己分配和管理,因此内存泄露的问题比较常见,同时也是很头痛的一件事情。而Java的对象生命周期管 理都是JVM来做的,简化了开发人员的非业务逻辑的处理,但是这种自动管理回收机制也是基于一些规则的,而违背了这些规则的时候,就会造成所谓的 “Memory Leak”。
OOM(Java Heap)
       错误提示:java.lang.OutOfMemoryError。
这 类OOM是由于JVM分配的给应用的Heap Memory已经被耗尽,可能是因为应用在高负荷的情况下的却需要很大的内存,因此可以通过修改JVM参数来增加Java Heap Memory(不过也不能无限制增加,后面那种OOM有可能就是因为这个原因而产生)。另一种情况是因为应用程序使用对象或者资源没有释放,导致内存消耗 持续增加,最后出现OOM,这类问题引起的原因往往是应用已不需要的对象还被其他有效对象所引用,那么就无法释放,可能是业务代码逻辑造成的(异常处理不 够例如IO等资源),也可能是对于第三方开源项目中资源释放了解不够导致使用以后资源没有释放(例如JDBC的ResultSet等)。
       几个容易出现问题的场景:
       1.应用的缓存或者Collection:如果应用要缓存Java对象或者是在一个Collection中保存对象,那么就要确定是否会有大量的对象存入,要做保护,以防止在大数据量下大量内存被消耗,同时要保证Cache的大小不会无限制增加。
       2.生命周期较长的对象:尽量简短对象的生命周期,现在采用对象的创建释放代价已经很低,同时作了很好的优化,要比创建一个对象长期反复使用要好。如果能够设置超时的情景下,尽量设置超时。
       3.类似于JDBC的Connection Pool,在使用Pool中的对象以后需要释放并返回,不然就会造成Pool的不断增大,在其他Pool中使用也是一样。同样ResultSet,IO这类资源的释放都需要注意。
       解决的方法就是查找错误或者是增加Java Heap Memory。对于此类问题检测工具相当多,这里就不做介绍了。      
OOM(Native Heap)
错误提示:requested XXXX bytes for ChunkPool::allocate. Out of swap space。
       Native Heap Memory是JVM 内部使用的Memory,这部分的Memory可以通过JDK提供的JNI的方式去访问,这部分Memory效率很高,但是管理需要自己去做,如果没有把 握最好不要使用,以防出现内存泄露问题。JVM 使用Native Heap Memory用来优化代码载入(JTI代码生成),临时对象空间申请,以及JVM内部的一些操作。这次同事在压力测试中遇到的问题就是这类OOM,也就是 这类Memory耗尽。同样这类OOM产生的问题也是分成正常使用耗尽和无释放资源耗尽两类。无释放资源耗尽很多时候不是程序员自身的原因,可能是引用的 第三方包的缺陷,例如很多人遇到的Oracle 9 JDBC驱动在低版本中有内存泄露的问题。要确定这类问题,就需要去观察Native Heap Memory的增长和使用情况,在服务器应用起来以后,运行一段时间后JVM对于Native Heap Memory的使用会达到一个稳定的阶段,此时可以看看什么操作对于Native Heap Memory操作频繁,而且使得Native Heap Memory增长,对于Native Heap Memory的情况我还没有找到办法去检测,现在能够看到的就是为JVM启动时候增加-verbose:jni参数来观察对于Native Heap Memory的操作。另一种情况就是正常消耗Native Heap Memory,对于Native Heap Memory的使用主要取决于JVM代码生成,线程创建,用于优化的临时代码和对象产生。当正常耗尽Native Heap Memory时,那么就需要增加Native Heap Memory,此时就会和我们前面提到增加java Heap Memory的情况出现矛盾。
应用内存组合
       对 于应用来说,可分配的内存受到OS的限制,不同的OS对进程所能访问虚拟内存地址区间直接影响对于应用内存的分配,32位的操作系统通常最大支持4G的内 存寻址,而Linux一般为3G,Windows为2G。然而这些大小的内存并不会全部给JVM的Java Heap使用,它主要会分成三部分:Java Heap,Native Heap,载入资源和类库等所占用的内存。那么由此可见,Native Heap和 Java Heap大小配置是相互制约的,哪一部分分配多了都可能会影响到另外一部分的正常工作,因此如果通过命令行去配置,那么需要确切的了解应用使用情况,否则 采用默认配置自动监测会更好的优化应用使用情况。
       同样要注意的就是进程的虚拟内存和机器的实际内存还是有区别的,对于机器来说实际内存以及硬盘提供的虚拟内存都是提供给机器上所有进程使用的,因此在设置JVM参数时,它的虚拟内存绝对不应该超过实际内存的大小。
《二》
       这 里首先要说明的是这里提到的JVM是Sun的HotSpot JVM 5和以上的版本。性能优化在应用方面可以有很多手段,包括Cache,多线程,各种算法等等。通常情况下是不建议在没有任何统计和分析的情况下去手动配置 JVM的参数来调整性能,因为在JVM 5以上已经作了根据机器和OS的情况自动配置合适参数的算法,基本能够满足大部分的情况,当然这种自动适配只是一种通用的方式,如果说真的要达到最优,那 么还是需要根据实际的使用情况来手动的配置各种参数设置,提高性能。
       JVM能够对性能产生影响的最大部分就是对于内存的管理。从jdk 1.5以后内存管理和分配有了很多的改善和提高。
内存分配以及管理的几个基本概念和参数说明:
Java Hotspot Mode:
server 和 client两种模式,如果不配置,JVM会根据应用服务器硬件配置自动选择模式,server模式启动比较慢,但是运行期速度得到了优化,client启动比较快,但是运行期响应没有server模式的优化,适合于个人PC的服务开发和测试。
Garbage Collector Policy:
       在Jdk 1.5的时候已经提供了三种GC,除了原来提供的串行GC(SerialGC)以外,还提供了两种新的GC:ParallelGC和 ConcMarkSweepGC。ParallelGC采用了多线程并行管理和回收垃圾对象,提高了回收效率,提高了服务器的吞吐量,适合于多处理器的服 务器。ConcMarkSweepGC采用的是并发方式来管理和回收垃圾对象,降低垃圾回收产生的响应暂停时间。这里说一下并发和并行的区别,并发指的是 多个进程并行执行垃圾回收,那么可以很好的利用多处理器,而并行指的是应用程序不需要暂停可以和垃圾回收线程并发工作。串行GC适合小型应用和单处理器系 统(无需多线程交互,效率比较高),后两者适合大型系统。
       使用方式就是在参数配置中增加-XX:+UseParallelGC等方式来设置。
       对于这部分的配置在网上有很多的实例可以参考,不过最终采用哪一种GC还是要根据具体的情况来分析和选择。
Heap:
       OOM的 各种经历已经让每一个架构师开发人员看到了了解Heap的重要性。OOM已经是Heap的临界点,不得不引起注意,然而Heap对于性能的潜在影响并未被 引起重视,不过和GC配置一样,在没有对使用情况作仔细分析和研究的情况下,贸然的去修改Heap配置,可能适得其反,这里就来看一下Heap的一些概念 和对于性能的影响。
       我们的应用所能够得到的最大的Heap受三部分因素的制约:数据处理 模型(32位或者64位操作系统),系统地虚拟内存总数和系统的物理内存总数。首先Heap的大小不能超过不同操作系统的进程寻址范围,当前大部分系统最 高限度是4G,Windows通常是2G,Linux通常是3G。系统的虚拟内存也是分配的依据,首先是不能超过,然后由于操作系统支持硬盘来做部分的虚 拟内存,如果设置过大,那么对于应用响应来说势必有影响。再则就是要考虑同一台服务器上运行多个Java虚拟机所消耗的资源总合也不能超过可用资源。就和 前面OOM分析中的一样,其实由于OS的数据处理模型的限制,机器本身的硬件内存资源和虚拟内存资源并不一定会匹配,那么在有限的资源下如何调整好资源分 配,对于应用来说尤为重要。
关于Heap的几个参数设置:
       说了Heap的有限资源问题以后,就来看看如何通过配置去改变JVM对于Heap的分配。下面所说的主要是对于Java Heap的分配,那么在申请了Java Heap以后,剩下的可用资源就会被使用到Native Heap。
       Xms: java heap初始化时的大小。默认情况是机器物理内存的1/64。这个主要是根据应用启动时消耗的资源决定,分配少了申请起来会降低启动速度,分配多了也浪费。
       Xmx:java heap的 最大值,默认是机器物理内存的1/4,最大也就到1G。这个值决定了最多可用的Java Heap Memory,分配过少就会在应用需要大量内存作缓存或者零时对象时出现OOM的问题,如果分配过大,那么就会产生上文提到的第二类OOM。所以如何配置 还是根据运行过程中的分析和计算来确定,如果不能确定还是采用默认的配置。
       Xmn:java heap新 生代的空间大小。在GC模型中,根据对象的生命周期的长短,产生了内存分代的设计:青年代(内部也分成三部分,类似于整体划分的作用,可以通过配置来设置 比例),老年代,持久代。每一代的管理和回收策略都不相同,最为活跃的就是青年代,同时这部分的内存分配和管理效率也是最高。通常情况下,对于内存的申请 优先在新生代中申请,当内存不够时会整理新生代,当整理以后还是不能满足申请的内存,就会向老年代移动一些生命周期较长的对象。这种整理和移动会消耗资 源,同时降低系统运行响应能力,因此如果青年代设置的过小,就会频繁的整理和移动,对性能造成影响。那是否把年青代设置的越大越好,其实不然,年青代采用 的是复制搜集算法,这种算法必须停止所有应用程序线程,服务器线程切换时间就会成为应用响应的瓶颈(当然永远不用收集那么就不存在这个问题)。老年代采用 的是串行标记收集的方式,并发收集可以减少对于应用的影响。
       Xss:线程堆栈最大值。允许更多的虚拟内存空间地址被Java Heap使用。
以下是sun公司的性能优化白皮书中提到的几个例子:
1.对于吞吐量的调优。机器配置:4G的内存,32个线程并发能力。
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
       -Xmx3800m -Xms3800m 配置了最大Java Heap来充分利用系统内存。
       -Xmn2g 创建足够大的青年代(可以并行被回收)充分利用系统内存,防止将短期对象复制到老年代。
    -Xss128 减少默认最大的线程栈大小,提供更多的处理虚拟内存地址空间被进程使用。
    -XX:+UseParallelGC 采用并行垃圾收集器对年青代的内存进行收集,提高效率。
    -XX:ParallelGCThreads=20 减少垃圾收集线程,默认是和服务器可支持的线程最大并发数相同,往往不需要配置到最大值。
2.尝试采用对老年代并行收集
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
-Xmx3550m -Xms3550m 内存分配被减小,因为ParallelOldGC会增加对于Native Heap的需求,因此需要减小Java Heap来满足需求。
-XX:+UseParallelOldGC 采用对于老年代并发收集的策略,可以提高收集效率。
3.提高吞吐量,减少应用停顿时间
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 选择了并发标记交换收集器,它可以并发执行收集操作,降低应用停止时间,同时它也是并行处理模式,可以有效地利用多处理器的系统的多进程处理。
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=31 表示在青年代中Eden和Survivor比例,设置增加了Survivor的大小,越大的survivor空间可以允许短期对象尽量在年青代消亡。
-XX:TargetSurvivorRatio=90 允许90%的空间被占用,超过默认的50%,提高对于survivor的使用率。
类似的例子网上很多,这儿就不在列下来了,最终是否采取自己配置来替换默认配置还是要根据虚拟机的使用情况来分析和配置。

分享到:
评论

相关推荐

    淘宝JVM优化实践-长仁.pdf

    《淘宝JVM优化实践》是一份深入探讨阿里巴巴集团核心系统研发部在JVM优化方面的实践经验的文档。这份文档主要涵盖了以下几个关键知识点: 1. **淘宝JVM优化背景**:随着淘宝、天猫等业务的快速发展,其Java应用规模...

    大厂架构师-日均百万订单量的JVM优化与高级GC调优策略实战(5.8G)

    大厂架构师-日均百万订单量的JVM优化与高级GC调优策略实战(5.8G) 〖课程介绍〗: 来自顶尖大厂的架构师级JVM优化与GC调优策略实战课程,是具备有尖端技术的优化课程。在课程内容上几乎不用过多的介绍,单是查阅目录就...

    JVM优化及面试热点分析-完整版.pdf

    ### JVM优化及面试热点分析 #### 一、Java技术概览与重要性 Java作为一门历史悠久且广泛应用的编程语言,其重要性和影响力不言而喻。根据TIOBE编程语言排行榜,Java一直稳居首位,这不仅是因为它拥有庞大的开发者...

    JVM优化方案

    在JVM优化中,内存配置是关键的一环。例如,`-Xms2048m -Xmx2048m`设置了JVM的最小和最大堆内存为2GB,`-Xmn512m`指定了新生代的大小为512MB,`-XX:MaxPermSize=256m`设定了永久代的最大值为256MB,而`-Xss128k`则...

    JVM优化方法

    JVM优化方法

    JVM优化|java虚拟机优化

    - 了解下我们为什么要学习JVM优化 - 掌握jvm的运行参数以及参数的设置 - 掌握jvm的内存模型(堆内存) - 掌握jamp命令的使用以及通过MAT工具进行分析 - 掌握定位分析内存溢出的方法 - 掌握jstack命令的使用 - 掌握...

    jvm优化中文版

    为了深入理解JVM优化的相关知识点,我们可以从多个角度来探讨。首先,需要理解JVM(Java虚拟机)的基本概念,以及在性能调优中的关键作用。JVM是运行Java程序的核心组件,负责解释Java字节码,并将字节码转换成特定...

    jvm优化参数配置

    "jvm优化参数配置"是确保Tomcat稳定运行的关键环节,能够提高应用的响应速度,减少内存泄露,提升系统整体性能。以下是对JVM参数优化的详细解释: 1. **内存配置**: - **堆内存(Heap Memory)**:分为新生代...

    JVM优化经验总结Java开发Java经验技巧共15页.p

    【标题】"JVM优化经验总结Java开发Java经验技巧共15页.p" 提供的信息表明,这是一份关于Java开发中的JVM优化经验的详细总结,共有15页的内容。在Java开发过程中,理解并掌握JVM(Java虚拟机)的优化技巧是至关重要的...

    JVM优化3(Tomcat参数调优,JVM参数调优,jvm字节码,代码优化).pdf

    本篇文件内容主要介绍了JVM优化的第三部分,重点围绕Tomcat参数调优、JVM参数调优、JVM字节码优化以及代码优化等几个方面。下面是针对这些知识点的详细解释: 1. Tomcat参数调优 在Tomcat参数调优部分,首先介绍了...

    Jvm优化的Java -Demo

    "Jvm优化的Java - Demo"是一个项目,旨在演示如何调整JVM参数来优化Java应用程序的性能。通过这个项目,我们可以学习到JVM调优的一些核心概念和实践技巧。 首先,JVM参数调整是提高应用程序性能的重要手段。这通常...

    JVM优化.docx

    【JVM优化】Java的JVM优化涉及到许多关键知识点,主要目标是确保应用程序在生产环境中稳定、高效地运行。在本地开发环境中,由于资源限制不严,通常不需要过多关注JVM优化,但在生产环境中,面临如应用卡死、日志无...

    JVM优化3(Tomcat参数调优,JVM参数调优,jvm字节码,代码优化).zip

    这个压缩包文件"JVM优化3(Tomcat参数调优,JVM参数调优,jvm字节码,代码优化).zip"显然包含了关于如何优化Java应用程序运行效率的四个主要方面:Tomcat服务器的参数调整、JVM参数调优、JVM字节码理解和优化以及代码...

    JVM优化day01.pdf

    本知识点将详细介绍JVM内存优化相关的概念和工具,帮助初学者快速掌握JVM优化的入门知识。 首先,了解JVM堆内存的设置是非常重要的。堆内存是JVM所管理的内存中最大的一块,主要用于存放对象实例。堆的大小对Java...

    jvm优化学习资源学习及讲义说明

    在"jvm优化学习资源学习及讲义说明"中,我们可以深入探讨以下几个关键知识点: 1. **JVM架构**:了解JVM的内存模型,包括堆内存(Heap)、方法区(Method Area)、栈内存(Stack)、本地方法栈(Native Method ...

    JVM优化与OOM分析PPT

    ### JVM优化与OOM分析 #### 一、JVM的重要性与作用 JVM(Java Virtual Machine)作为Java程序的运行环境,对于确保Java程序能够跨平台运行具有重要意义。它不仅提供了执行字节码的基础,还负责内存管理、垃圾回收...

    java第五阶段(项目梳理+面试题准备+jvm优化+mysql优化)

    "java第五阶段(项目梳理+面试题准备+jvm优化+mysql优化)"这个主题涵盖了多个关键的知识领域,对于提升Java开发者的技术深度和面试竞争力至关重要。以下是这些领域的详细解释: 1. **JVM优化**:Java虚拟机(JVM)...

    37-JVM优化1

    在Java开发中,JVM(Java Virtual Machine)的优化是提升应用程序性能的关键环节。本文主要围绕HotSpot JVM的优化展开,旨在防止出现内存溢出...记住,JVM优化是一个持续的过程,需要根据应用的实际运行情况进行调整。

Global site tag (gtag.js) - Google Analytics