一、打开了数据库和LDAP连接后,用完后忘记关闭,导致程序上线运行后一段时间会出现无法访问情况,因连接用完。采用用连接池技术+Spring的数据连接事务管理。
二、ClassLoader初始化配置文件程序很长多大8千行,进行了很多冗余臃肿的加载和jar加载,导致启动web容器时加载内存溢出。错误实例:
1) java.lang.OutOfMemoryError: PermGen space
PermGen space 的全称是 Permanent Generation space, 是指内存的永久保存区域。这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGenspace中,它和存放类实例(Instance)的Heap区域不同,GC不会在主程序运行期对PermGen space进行清理。
JVM由XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
JVM由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
该错误常见场合:
a) 应用中有很多Class,web服务器对JSP进行precompile时。
b) Webapp下用了大量的第三方jar,其大小超过了JVM默认的大小(4M)时。
三、全局集合要精简冗余。初始化加载session时加载了一些对象,这些对象又引用的其他对象,导致一些被引用对象长期在虚拟机得不到释放。例如:session加载了list,list又加载了很多对象。
四、隐形内存泄漏,密码计划程序,运行一个计划时间会很长,其中用到多线程,在程序运行过程中,很多对象一直被逐步加载一直到程序运行完才释放。应该在运行过程中逐步释放利用过的资源。
五、读取LDAP和数据库数据时进行全部查询读取,未进行了分页查询和条件查询。导致读取的数据一次过多内存溢出。例如:
2) java.lang.OutOfMemoryError:Javaheap space
在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。
JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;
JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。
JVM内存的最大值跟操作系统有很大的关系。32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。
注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。
该错误常见场合:
a) Web上传文件时。
b) 开启大型文件或从数据库中一次取了太多的数据。
六、Java中循环里引用了new对象导致循环后未及时释放循环集合。
A: Java中也存在内存泄露。当被分配的对象可达但已无用(未对作废数据内存单元的引用置null)即会引起。
如:
Java代码
Vector v=new Vector(10); for(int i=1;i<100; i ) { Object o=new Object(); v.add(o); o=null; } // 此时,所有的Object对象都没有被释放,因为变量v引用这些对象。 // 对象加入到Vector后,还必须从Vector中删除,最简单释放方法就是将Vector对象设置为null。
七、应用缓存方法不当,导致缓存无限扩大。原始采用缓存为hashmap
1 、无法高效的控制缓存把最久的不长用的移除缓存。2、修改了缓存数据没有同步修改数据库,或者修改了数据库没有同步修改缓存。3、当部署多台WEB服务时,因为没有缓存同步情况,照成两台机器的缓存数据不一致。
八、程序进行字符串连接处理时,尽量避免使用String,而应使用StringBuffer。
因为每一个String对象都会独立占用内存一块区域,如:
Java代码
String str = "aaa";String str2 = "bbb"; String str3 = str str2; // 假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收; // 假如程序中存在过多的类似情况就会出现内存错误;
九、尽量少用静态变量。
因为静态变量是全局的,GC不会回收。
十、避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。例如上传和下载大文件时。
JVM会突然需要大量内存,这时会触发GC优化系统内存环境; 一个案例如下:
Java代码
// 使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误, // 检查之后发现问题:组件里的代码 m_totalBytes = m_request.getContentLength(); m_binArray = newbyte[m_totalBytes]; // totalBytes这个变量得到的数极大,导致该数组分配了很多内存空间,而且该数组不能及时释放。 // 解决办法只能换一种更合适的办法,至少是不会引发outofMemoryError的方式解决。 // 参考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747
十一、尽早释放无用对象的引用。
好的办法是使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。
十二、程序进行字符串处理时,尽量避免使用String,而应使用StringBuffer。
因为每一个String对象都会独立占用内存一块区域,如:
Java代码
String str = "aaa";String str2 = "bbb"; String str3 = str str2; // 假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收; // 假如程序中存在过多的类似情况就会出现内存错误;
十三、尽量运用对象池技术以提高系统性能。
生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。
十四、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out OfMemory Error 的状况。这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值,通过分页或者流式进行加载。
十五、内存溢出的解决方案?
A: 一是从代码层面进行优化完善,尽量避免该情况发生;
二是调整优化服务器配置:
1) 设置-Xms、-Xmx相等;
2) 设置NewSize、MaxNewSize相等;
3) 设置Heap size, PermGen space:
Tomcat 的配置示例:修改%TOMCAT_HOME%/bin/catalina.bat or catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
Cmd代码