引入JVM,使得无需重新编译Java语言,就可以在不同的平台上运行。但在程序上线之前的测试或者运行过程中,会出现各种各样的JVM问题。实例CPUload太高,请求延迟,tps降低,甚至发生内存泄漏,造成系统崩溃等问题。这就需要在优化JVM的前提下,促使程序正常运行,以获得更高的用户体验和运行效率。
JVM如何对Java虚拟机进行优化。
查看存储器释放,集合类检查,目标树。
显示堆空间大小的分布情况(年轻的、老年的、持久的代分配)。
可以立即进行垃圾收集。废物监测(长期监测再循环)。
浏览堆内类,查看对象信息:数量,类型等。
查看对象参考情况。
通过查看堆信息的功能,我们通常能够顺利地解决下列问题:
--年轻代人口规模划分是否合理。
--内存泄漏。
——设置垃圾收集算法是否合理。
线程化信息监视:系统线程数。
线程态监视:每个线程都处于何种状态。
Dump线程细节:查看线程内部运行状态的死锁检查。
第一个:内存泄漏检查。
记忆体泄露是比较常见的问题,并且解决方法比较一般,在这里可以着重介绍,而线程、热点方面的问题就是具体问题具体分析了。
通常可以将内存泄漏理解为系统资源(所有方面的资源、堆、栈、线程等等)如果不正确地使用,会造成使用完的资源无法回收(或不回收),从而导致不能完成新的资源分配请求,造成系统错误。
存储器泄露对系统的危害是很大的,因为它会直接导致系统崩溃。
内存泄漏与系统负载之间存在着差别,尽管最终产生的结果是相同的。存储器泄露就是,耗尽的资源未回收会导致错误,而系统过载则是系统确实没有足够的资源可分配(其他资源正在使用)。
答案:
此方法解决起来也比较简单,一般是根据垃圾回收前后的情况进行对比,同时根据对象引用(共同的集合对象引用)分析,泄漏点基本上可以找出。
第二题:持续代数被占满。
例外情况:java.lang.OutOfMemoryError:PermGenspace。
解释:Perm空间已满。未能为新class分配存储空间时引发的异常。这一异常以前不存在,但如今Java反射的大量出现使得这种异常更加普遍。其主要原因是不断地装入动态反射的类,并最终造成Perm区占去。
更为糟糕的是,尽管不同的classLoader虽然使用同样的类,但还是会装载它,这等同于同一事物,如果你有N个classLoader,它就会装载N次。所以,在某些情况下,这个问题基本上是没有答案的。自然,几乎没有多少classLoader和大量反射类存在。
答案:
1.-XX:MaxPermSize=16m。
2.更换JDK。例如JRocket。
第三问:栈溢出。
例外情况:java.lang.StackOverflowError。
这个就不多说了,通常是指递归没有返回,或者循环调用所致。
线程堆栈已满。
例外情况:错误:启动状态。
解释:在java中,线程的空间大小受到限制。在JDK5.0之后,该值为1M。此线程相关的数据保存在该线程中。但上面的异常是在线程空间满了之后发生的。
处理:增大线程栈大小。-Xss2m。但是这种配置并不能解决根本问题,而是查看代码部分是否有导致泄漏的部分。
第五题:系统内存被占用。
例外情况:java.lang.OutOfMemoryError:unabletocreatenewnativethread。
解释:此异常是由操作系统资源不足导致的,无法生成此线程。当系统创建线程时,除了Java堆中的内存分配之外,操作系统本身还需要分配资源以创建线程。所以,当线程的数量较大时,堆中也许还有空间,但操作系统无法分配资源,这就会发生异常。
为Java虚拟机分配的内存越多,系统所剩的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么系统总能生成的线程就越少,这两者成反比关系。与此同时,通过修改-Xss,可以减少分配给各个线程的空间,或者增加系统产生的总数量。
答案:
1.重新设计系统,减少线程数。
2.如果无法减少线程数目,则使用-Xss减小单个线程大小。这样就可以生成更多线程。
上述内容与您分享了一些关于Java虚拟机之JVM优化的内容。在这一过程中,最重要的指标是:内存占用、延时和吞吐量。实践中,要同时达到三个指标,很难做到最优,因此调优时要根据程序的目的来调整。