出处1:http://www.iteye.com
写java程序时大家一定对一下两条异常并不陌生:
java.lang.OutOfMemoryError: Java heap space下面说正题:
下面写些代码来演示一下内存溢出的产生,堆转储文件的生成,堆内存的分析。
首先创建数据持有对象类:
package com.zas.jvm.om; /** * 数据对象 * @author zas */ public class DataObject { //数据对象ID private String id; //数据对象内容 private String des; public DataObject(String id, String des) { super(); this.id = id; this.des = des; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } @Override public String toString() { return "DataObject [id=" + id + ", des=" + des + "]"; } /** * @param args */ public static void main(String[] args) { } }
package com.zas.jvm.om; import java.util.ArrayList; import java.util.List; public class OutMemeryTest { Listlist = new ArrayList (); public void testOm(){ for (int i = 0; i < 100000; i++) { DataObject data = new DataObject("id&"+i, "des:"+i); list.add(data); } } /** * @param args */ public static void main(String[] args) { OutMemeryTest omt = new OutMemeryTest(); for (int i = 0; i < 2; i++) { omt.testOm(); } System.out.println("DOne!"); try { Thread.sleep(100000000); } catch (InterruptedException e) { e.printStackTrace(); } } }
-------------------------------------------------------------------------------------------------------------------------------------------------------------
1、 内存溢出的原因是什么?
内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查:
一)是否App中的类中和引用变量过多使用了Static修饰 如public staitc Student s;在类中的属性中使用 static修饰的最好只用基本类型或字符串。如public static int i = 0; //public static String str;
二)是否App中使用了大量的递归或无限递归(递归中用到了大量的建新的对象)
三)是否App中使用了大量循环或死循环(循环中用到了大量的新建的对象)
四)检查App中是否使用了向数据库查询所有记录的方法。即一次性全部查询的方法,如果数据量超过10万多条了,就可能会造成内存溢出。所以在查询时应采用“分页查询”。
五)检查是否有数组,List,Map中存放的是对象的引用而不是对象,因为这些引用会让对应的对象不能被释放。会大量存储在内存中。
六)检查是否使用了“非字面量字符串进行+”的操作。因为String类的内容是不可变的,每次运行"+"就会产生新的对象,如果过多会造成新String对象过多,从而导致JVM没有及时回收而出现内存溢出。
如String s1 = "My name";
String s2 = "is";
String s3 = "xuwei";
String str = s1 + s2 + s3 +.........;这是会容易造成内存溢出的
但是String str = "My name" + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是这种就不会造成内存溢出。因为这是”字面量字符串“,在运行"+"时就会在编译期间运行好。不会按照JVM来执行的。
在使用String,StringBuffer,StringBuilder时,如果是字面量字符串进行"+"时,应选用String性能更好;如果是String类进行"+"时,在不考虑线程安全时,应选用StringBuilder性能更好。
七)使用 DDMS工具进行查找内存溢出的大概位置
2、栈溢出的原因
一)、是否有递归调用
二)、是否有大量循环或死循环
三)、全局变量是否过多
四)、 数组、List、map数据是否过大
五)使用DDMS工具进行查找大概出现栈溢出的位置