关于Java中内存溢出的解决办法

开发 后端
J2EE应用系统是运行在J2EE应用服务器上的,而j2ee应用服务器又是运行在JVM上的,生成环境中JVM参数的优化和设置对于J2EE应用系统性能有着决定性的作用。

J2EE应用系统是运行在J2EE应用服务器上的,而j2ee应用服务器又是运行在JVM上的,生成环境中JVM参数的优化和设置对于J2EE应用系统性能有着决定性的作用。要优化系统,则需要对JVM参数进行合理的设置,所以我们需要了解究竟在什么地方进行设置、有哪些参数以及各参数的意义分别是什么,并且我们还得了解JVM的内存管理机制究竟是个什么玩意儿?其实我们在网上搜索引擎上,一搜就有可以获取到一大把相关信息,关键是我们如何深入的理解它们。那么下面我们就简单的介绍一下究竟什么是JVM的内存管理机制吧~!  

JVM的早期版本并没有进行分区管理;这样的后果是JVM进行垃圾回收时,不得不扫描JVM所管理的整片内存,所以搜集垃圾是很耗费资源的事情,也是早起JAVA程序的性能低下的主要原因。随着JVM的发展,JVM引进了分区管理的机制。

JVM所管理的所有内存资源分为2个大的部分。***存储区(Permanent Space) 和堆空间(The Heap Space)。其中对空间又分为新生区()和养老区,新生区又分为伊甸园,幸存者0区、幸存1区。如下图:

 

关于个分区的用途,大家可以参考其他相关文档。本教程所要处理的问题是如何解决内存溢出的问题。接下来以tomcat服务器为例:

我们首先得找到内存管理所要设置的参数在哪个文件:<CATALINA_HOME>/bin/catalina.bat。

需要添加一行代码:

JAVA_OPTS="-Xms512m-Xmx512m -Xss1024K -XX:PermSize=256m -XX:MaxPermSize=256m"

下面分别对各参数进行介绍和解释:

JVM 相关参数:

参数名参数说明

-server 启用能够执行优化的编译器, 显著提高服务器的性能,但使用能够执行优化的编译器时,服务器的预备时间将会较长。生产环境的服务器强烈推荐设置此参数。

-Xss 单个线程堆栈大小值;JDK5.0 以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

-XX:+UseParNewGC 可用来设置年轻代为并发收集【多CPU】,如果你的服务器有多个CPU,你可以开启此参数;开启此参数,多个CPU 可并发进行垃圾回收,可提高垃圾回收的速度。此参数和+UseParallelGC,-XX:ParallelGCThreads搭配使用。

+UseParallelGC 选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。可提高系统的吞吐量。

-XX:ParallelGCThreads 年轻代并行垃圾收集的前提下(对并发也有效果)的线程数,增加并行度,即:同时多少个线程一起进行垃圾回收。此值***配置与处理器数目相等。***存储区相关参数:参数名参数说明

-Xnoclassgc 每次***存储区满了后一般GC 算法在做扩展分配内存前都会触发一次FULL GC,除非设置了-Xnoclassgc.

-XX:PermSize 应用服务器启动时,***存储区的初始内存大

-XX:MaxPermSize 应用运行中,***存储区的极限值。为了不消耗扩大JVM ***存储区分配的开销,将此参数和-XX:PermSize这个两个值设为相等。堆空间相关参数参数名参数说明

-Xms 启动应用时,JVM 堆空间的初始大小值。

-Xmx 应用运行中,JVM 堆空间的极限值。为了不消耗扩大JVM 堆控件分配的开销,将此参数和-Xms 这个两个值设为相等,考虑到需要开线程,讲此值设置为总内存的80%.

-Xmn 此参数硬性规定堆空间的新生代空间大小,推荐设为堆空间大小的1/4。

上面所列的JVM 参数关系到系统的性能,而其中-XX:PermSize,

-XX:MaxPermSize,-Xms,-Xmx 和-Xmn 这5 个参数更是直接关系到系统的性能,系统是否会出现内存溢出。

-XX:PermSize 和-XX:MaxPermSize 分别设置应用服务器启动时,***存储区的初始大小和极限大小;在生成环境中强烈推荐将这个两个值设置为相同的值,以避免分配***存储区的开销,具体的值可取系统“疲劳测试”获取到的***存储区的极限值;如果不进行设置-XX:MaxPermSize 默认值为64M,一般来说系统的类定义文件大小都会超过这个默认值。

-Xms 和-Xmx 分别是服务器启动时,堆空间的初始大小和极限值。-Xms的默认值是物理内存的1/64 但小于1G,-Xmx 的默认值是物理内存的1/4 但小于1G.在生产环境中这些默认值是肯定不能满足我们的需要的。也就是你的服务器有8g 的内存,不对JVM 参数进行设置优化,应用服务器启动时还是按默认值来分配和约束JVM 对内存资源的使用,不会充分的利用所有的内存资源。

结论:“***存储区溢出(java.lang.OutOfMemoryError:Java Permanent Space)”乃是***存储区设置太小,不能满足系统需要的大小,此时只需要调整-XX:PermSize 和-XX:MaxPermSize 这两个参数即可。“JVM 堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM 堆空间不足,此时只需要调整-Xms 和-Xmx 这两个参数即可。

到此我们知道了,当系统出现内存溢出时,是哪些参数设置不合理需要调整。但我们怎么知道服务器启动时,到底JVM 内存相关参数的值是多少呢?

这个问题其实Sun公司早已经意料到了,所以给我们开发了内存使用监控工具jvmstat.

大家可以到ORACLE官网进行下载。用它可以很方便的看到我们的服务器内存使用情况。

将下载的jvmstat包解压到如“C:\ProgramFiles\Java\jvmstat”(这是我本地java路径,大家可以根据自己所安装的java环境的路径进行解压)。启动完之后我们就可以使用visualgc命令了,cmd进入命令符窗口,输入tasklist(windows下查看进程任务PID)查找到你要检测进程PID.然后直接输入visuglgc PID 就会弹出三个可见视图。

如下图:

 

原文链接:http://blog.csdn.net/czp0608/article/details/7352024

【编辑推荐】

  1. Java中的面向对象特性
  2. 探究Java初始化的过程
  3. Java集合框架的知识总结
  4. Java与F#的并行程序处理对比
  5. Java并发编程之同步互斥问题
责任编辑:林师授 来源: czp0608的博客
相关推荐

2019-08-29 14:29:42

JVM内存 Java

2009-08-18 16:45:50

Tomcat内存溢出

2012-05-29 16:30:33

Tomcat内存溢出

2009-09-17 14:11:53

2010-04-13 14:54:06

Oracle SQL

2009-09-03 09:08:08

Linuxroot密码遗忘

2009-06-16 11:01:14

Java内存溢出

2010-01-12 15:36:17

三层路由交换机

2009-06-03 16:41:21

Eclipse乱码Eclipse

2011-03-04 13:07:47

Filezilla

2021-03-06 10:25:19

内存Java代码

2024-09-09 09:41:03

内存溢出golang开发者

2011-01-19 17:54:48

2009-05-31 09:07:35

Oracle锁定

2011-06-17 11:10:51

Qt 中文 输出

2021-02-03 15:12:08

java内存溢出

2023-08-28 10:54:09

容器Docker

2009-12-07 18:38:16

WCF异常

2010-01-15 09:38:08

磁盘被写保护解决办法

2017-05-04 20:15:51

iOSNSTimer循环引用
点赞
收藏

51CTO技术栈公众号