Java虚拟机性能调优垃圾回收与错误排查
Java虚拟机是我们在学习java编程开发技术的时候需要重点掌握的编程知识之一,而今天我们就通过案例分析来了解一下,Java虚拟机性能调优中垃圾回收与错误排查方法。
1、垃圾回收
垃圾检测:引用计数法和可达性分析算法。
引用计数法:给一个对象添加引用计数器,每当有个地方引用它,计数器就加1,引用失效就减1。如果对象互相引用,那么就导致内存泄漏,所以这个方法已经被废弃。
可达性分析算法:以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象。这里的根集一般包括java栈中引用的对象、方法区常量池中引用的对象和本地方法中引用的对象等。JVM在做垃圾回收的时候,会检查堆中的所有对象是否会被这些根集对象引用,不能够被引用的对象就会被垃圾收集器回收。
年轻代被分为3个部分,Enden区和两个Survivor区。当Eden区被对象填满时,就会执行MinorGC,并把所有存活下来的对象转移到其中一个survivor区。MinorGC同样会检查先前存活下来的对象,也把它们转移到这个survivor区。这样在一段时间内,总会有一个空的survivor区。经过多次GC周期后,仍然存活下来的对象会被转移到年老代内存空间。
年老代存放的都是生命周期较长的对象。通常会在老年代内存被占满时将会触发FullGC,回收整个堆内存。
2、错误排查:
常见场景:CPU狂飙,通过ps-opcpu,pid,tid找出是哪些线程在高频率的使用CPU,然后使用jstack命令找出这些线程,如果是普通线程,它的callstack直接反映出问题所在。如果是GC线程,通过gc日志可以看出GC线程在拼命GC,但是GC前后效果不明显,已用堆内存始终降不下来,其它线程会表现为alloc_enqueue_allocation_and_wait_for_gc的native_blocked阻塞状态,此时用jmap命令dump堆内存情况,使用eclipseMAT工具找出问题所在。
很多时候性能异常表现为偶然性,就是在不定的时间出现问题,此时通过给jvm加启动参数来生成转储文件,然后事后分析。-verbose:gc-Xloggc:xxx.txt生成gc日志,-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=yyy.txt在OOM出现后自动生成了堆转储文件,据此可分析堆和线程的情况。
内存溢出outofmemory,是指程序在申请内存时,没有足够的内存空间供其使用,出现outofmemory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露memoryleak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memoryleak会终会导致outofmemory!
以下为常见的内存错误: java.lang.OutOfMemoryError:Javaheapspace堆空间被占满 java.lang.OutOfMemoryError:PermGenspace持久代被占满(1.8之前版本) java.lang.StackOverflowError线程栈溢出 Fatal:Stacksizetoosmall线程localarea满 java.lang.OutOfMemoryError:unabletocreatenewnativethread系统内存被占满