jvm性能调优具体例子(性能测试能力提升-JVM)
jvm性能调优具体例子(性能测试能力提升-JVM)GC工作原理:当应用线程在运行 并在运行过程中创建新对象 若这时内存空间不足 JVM就会强制地调用GC线程 以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求 JVM会再进行两次GC作进一步的尝试 若仍无法满足要求 则 JVM将报“out of memory”(内存溢出)的错误 Java应用将停止。对于Java程序员来说,一个对象的内存分配是在虚拟机的自动内存分配机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,而且不容易出现内存泄露和内存溢出问题,但是,如果出现了内存泄露和内存溢出问题,而开发者又不了解虚拟机是怎么分配内存的话,那么定位错误和排除错误将是一件很困难的事情。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。名词解释:Garbage Collections 字面意思
一、背景接着上一篇的知识:性能测试能力提升-长连接、短连接、连接池,本篇文章,我们将主要介绍JVM GC原理相关的知识:
- 什么是JVM
- 什么是GC
- JVM体系结构中GC作用区域
- JVM GC分代管理和流转过程
- JVM GC收集器介绍
什么是JVM
名词解释:JVM是java Virtual Machine(Java虚拟机)的缩写;
JVM的作用:
Java语言的一个非常重要的特点就是与平台的无关性,可以跨平台执行。而使用Java虚拟机是实现这一特点的关键。
一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。
2.2 什么是GC名词解释:
Garbage Collections 字面意思是垃圾回收器,释放垃圾占用的空间。
GC的作用:
让创建的对象不需要像c、c 那样delete、free掉 。对于c、c 的开发人员来说内存是开发人员分配的,也就是说还要对内存进行维护和释放。
对于Java程序员来说,一个对象的内存分配是在虚拟机的自动内存分配机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,而且不容易出现内存泄露和内存溢出问题,但是,如果出现了内存泄露和内存溢出问题,而开发者又不了解虚拟机是怎么分配内存的话,那么定位错误和排除错误将是一件很困难的事情。
GC工作原理:
当应用线程在运行 并在运行过程中创建新对象 若这时内存空间不足 JVM就会强制地调用GC线程 以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求 JVM会再进行两次GC作进一步的尝试 若仍无法满足要求 则 JVM将报“out of memory”(内存溢出)的错误 Java应用将停止。
堆(heap):
它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。
1.堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的
2.Sun Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配
3.TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。
方法区(Method Area)
1.在Sun JDK中这块区域对应的为PermanetGeneration,又称为持久代。
2.方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
2.4 JVM GC分代管理和流转过程
GC分为永久代(对应方法区)、新生代(Eden,S0,S1区域)、老年代(Old区域)。
永久代:存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,可能会被占满,触发GC。
新生代:存放生命周期较短的对象,GC频率高。
老年代:存放新生代中经历多次GC依然存活的对象,新建的对象也有可能直接在老生代分配(比如大对象),取决于具体GC的实现。GC频率相对较低。
GC类型主要分为:
MinorGC/YoungGC:只是新生代(Eden,S0,S1)的垃圾收集
MajorGC/OldGC:只是老年代的垃圾收集。
FullGC:收集整个java堆(新生代、老年代)和方法区(永久代)的垃圾收集。
注意:只有CMS收集器会有单独收集老年代的行为,其他收集器均无此行为,老年代空间不足会直接触发Full GC。而针对新生代的MinorGC,各个收集器均支持。总之,单独发生收集行为的只有新生代,除了CMS收集器,都不支持单独回收老年代。这也是为什么我们经常提到的只有Young GC和Full GC,而很少提到Old GC的原因。
流转过程:
EdenSpace(Eden区一次Young GC)=》FromSpace(S0区一次Young GC)=》ToSpace(S1区一次Young GC)=》对象移至老生代=》老年代空间不足=》触发Full GC
触发Full GC的常见情况:
1.System.gc()方法的调用:此方法的调用是建议JVM进行Full GC 虽然只是建议而非一定 但很多情况下它会触发 Full GC 从而增加Full GC的频率 也即增加了间歇性停顿的次数。强烈影响系统性能。建议能不使用此方法就别使用,让虚拟机自己去管理它的内存,可通过通过-XX: DisableExplicitGC来禁止RMI调用System.gc。
2.老年代空间不足:如果某个(些)对象(原来在内存中存活的对象或者新创建的对象)由于以上原因需要被移动到老年代中,而老年代中没有足够空间容纳这个(些)对象,那么会触发一次Full GC。
3.永久代空间不足:Permanet Generation(方法区)中存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下也会执行Full GC。
Full GC的执行时间比Minor GC要长很多。因此,如果Full GC花费了太多的时间(比如超过1秒),一些连接的部分可能会发生超时错误。要尽量减少触发Full GC。
2.5 JVM GC收集器介绍
各类收集器解释:
- 单线程GC收集器包括Serial和SerialOld这两款收集器,分别用于年轻代和老年代的垃圾收集工作;
- ParNew收集器其实就是Serial收集器的多线程版本;
- Parallel Scavenge收集器类似ParNew收集器,Parallel Scavenge收集器更关注系统的吞吐量;
- Parallel Old是Parallel Scavenge收集器的老年代版本;
- CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器;
- G1垃圾收集器:Jdk7的新特性之一,未来计划替代CMS。目前CMS依然是主流;
常用组合搭配:
- Serial SerialOld,只能适用于单核CPU,单机程序;
- ParNew CMS ,在意服务器的响应时间,希望系统停顿时间最短,适用于互联网应用;
- Parallel Scavenge Parallel Old , 在意服务器吞吐量,适用于后台计算任务服务器;
- G1垃圾收集器:Jdk7的新特性之一,未来计划替代CMS。目前CMS依然是主流;
=================================
以上就是本次的全部内容,下一篇文章,我们将主要介绍以下方面的知识:
- GC监控相关知识
- GC优化相关知识
如果对你有帮助,欢迎关注我的程序员杨叔,各类文章都会第一时间在上面发布,持续分享全栈测试知识干货,你的支持就是作者更新最大的动力~