java.lang.OutOfMemoryError引来的一系列之Java内存管理
最近网站出现了OutOfMemoryError.
http://japi.iteye.com/blog/261586
对Java的内存管理又深入学习.
过去的学习知道:
Java的内存分为堆与栈,类都在椎上,方法变量都在栈上.
Java中使用垃圾回收机制,减轻了程序员的负担.
Java的垃圾回收机制不等于C++中的析构函数.
Java的垃圾回收机制,程序员只能通过System.gc(),Object.finalize()方法来建议JVM运行垃圾回收.
Java虽然有垃圾回收机制,但也会出现内存溢出.
----------------------------------
以上,学了Java的人都知道.
那还一些不知道的东西.比如:网站报错:PerGen space就不知道是什么东西.
第一步再深入垃圾回收机制
http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/index.html
这篇文章讲了基本的原理,以及运用有向图解释了Java与C++的不同.
对于C++程序需要管理节点与边,而Java只需要管理边.这就提高了编程效率.
由此我们要特别加深印象:Java也是会有内存溢出的,只是范围相对C++来说小了点.
第二步再进一步理解垃圾回收机制
知道Java中的对象都存放在堆上,内存有堆与栈的区别是不够的.
必须进一步细分
http://blog.csdn.net/calvinxiu/archive/2007/05/18/1614473.aspx
http://hi.baidu.com/xuwanbest/blog/item/0587d82f2c44a73d1e30892e.html
http://aleung.blogbus.com/logs/4712392.html
以上三篇介绍了垃圾回收机制的回收算法,以及堆的细分
回收算法有三种:
一是复制法:将椎分成两块A,B.从根开始遍历A中的所有活动对象,复制到B中,一次性回收A.
这样做只需遍历活动对象不需访问死对象,减小了遍历成本,但得付出巨大复制
代价和较多的内存.
二是标记清除法:先访问所有活动对象并标记,再访问所有内存空间,把没有标记的对象清除.
遍历成本会随着空间大小线性增加,而且增加碎片.
三是标记整理法:结合以上两种算法的优点.标记活动对象,复制合并成大的内存块.
在以上三种方法之上,又改进了更好的方法:分代
分代成三种:Young , Old, Permanent.
Young:存放生命周期比较短的对象.选用复制算法回收.
这个区域又分为三个区域:一个Eden,存放新生的对象,两个Survivor(from,to).每次复制就是将Eden和第一块Survior的活对象复制到第2块.对Eden,第一个Survivor进行minor collection(只对Young区回收).
Old:年轻代的对象如果能够挺过数次收集,就会进入老人区.采用复制算法就要反复的复制对象,很不合算,只好采用标记清理算法.
Permanent:
装载Class信息等基础数据,默认64M,如果是类很多很多的服务程序,需要加大其设置-XX:MaxPermSize=,否则它满了之后会引起fullgc()或Out of Memory。 注意Spring,Hibernate这类喜欢AOP动态生成类的框架需要更多的持久代内存。
3 楼 east_java 2009-07-21 引用Linux:
在/usr/local/apache-tomcat-5.5.23/bin目录下的catalina.sh
添加:JAVA_OPTS='-Xms512m -Xmx1024m'
要加“m”说明是MB,否则就是KB了,在启动tomcat时会报内存不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值
Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m
如果用startup.bat启动tomcat,OK设置生效.够成功的分配200M内存.
但是如果不是执行startup.bat启动tomcat而是利用windows的系统服务启动tomcat服务,上面的设置就不生效了,
就是说set JAVA_OPTS=-Xms128m -Xmx350m 没起作用.上面分配200M内存就OOM了..
windows服务执行的是bin\tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置.