天天看点

关于内存溢出OutOfMemory

以下不算是教程,完全可以作为一个开胃菜,思考下。

相信百度“java内存溢出”或者“java内存泄漏”的文章,都会有很多详细描述,代码举例。这里推荐我看过的文章。

http://blog.csdn.net/anxpp/article/details/51325838

再说下我之前的面试经历。

被问到印象深刻的编程经历,当时自己写个关于【在指定文件夹下的文件中查找指定字符串】的程序,然后这个程序其实写出来大家都会觉得简单,确实如此。但是如果这些文件比较多,每个文件都比较大呢,我的代码确实出现了问题,具体如下:

在文件名带有【anr】和【crash】的文件夹中的所有文件中找到【Process】和【Flags】字符串中间的内容,并反馈属于哪个文件。我刚开始写的代码如下,使用的是jdk1.6。

package cn.com.tianll.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
  遍历某文件夹下的文件txt,找到指定txt文件并返回该txt文件中指定的字符串 
  @author tianll
  2016-7-13 22:36:54
 */
public class FindInfo {
    private static ArrayList<String> filelist = new ArrayList<String>();//用于存储跟文件夹名称
    private static String str = "";//用于存储某个文件中需要的信息
    private static String strsum = "";//用于存储遍历所有文件夹后的需要的信息
    public static void main(String args[]) throws IOException{
        String filePath = "H:\startdima\2016_06_27_13_29_58_ap_log\sdcard";
        getFiles(filePath);
    }

    private static void getFiles(String filePath) throws IOException {
        File root = new File(filePath);
        File[] files = root.listFiles();
        for(File file : files)   {
            String path = "";
            if(file.isDirectory()){
                path = file.getAbsolutePath();
                getFiles(path);
                filelist.add(path);
//              System.out.println("111显示"+filePath+"下所有子目录及其文件"+path);
            }else{
//              System.out.println("222显示"+filePath+"下所有子目录"+file.getAbsolutePath());
                //如果文件是txt文件,则查看文件名是否含有指定字符名称anr和crash
                path = file.getAbsolutePath();
//              if(path.contains(".xml")){
                     
                    if(path.contains("anr")||path.contains("crash")){
                        System.out.println("----------------"+path);
                        BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
                        String line = "" ;//表示读取的每行xml信息
                        str = "";
                        while((line =bf.readLine()) != null){
                            System.out.println("*"+line);
                            str = str+"\r\n"+line ;
                        }
                        if(str.contains("Process")&&str.contains("Flags")){
                            int index1 = str.indexOf("Process")+7;
                            int index2 = str.indexOf("Flags")+5;
                            System.out.println(index1);
                            System.out.println(index2);
                            if(index1<index2){
                                str = str.substring(index1 , index2);
                            }
                        }
//                      if(str.contains("000597922950008")){
//                          System.out.println(path+"+++");
//                      }
                    }
//              }
                strsum = strsum +str ;
                System.out.println("strsum="+strsum);
            }
        }
    }
}
           

之后面试说了这件事,问我原因,当时没有在意这个问题,直到我后来看了写内存泄露内存溢出的文章恍然大悟。测试文件比较小的时候没什么问题,文件多而且大的时候会出现OutOfMemory问题,这时候就需要优化代码了。优化如下,使用jdk1.7。具体更换jdk原因可以看内存泄漏中substring()方法在1.6和1.7中的区别,在1.7中移除永久代中的字符常量池。

package cn.com.tianll.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
  遍历某文件夹下的文件txt,找到指定txt文件并返回该txt文件中指定的字符串

  @author tianll 复制FindInfo
  2018-1-5 15:16:42,就行修改,已经修改完成。
 */
public class FindInfo1 {
    private ArrayList<String> filelist = new ArrayList<String>();// 用于存储跟文件夹名称
    private StringBuffer str = new StringBuffer();// 用于存储某个文件中需要的信息
    private String strString = "";
    private StringBuffer strA = new StringBuffer();// 用于存储某个文件中需要的信息 当前行
    private StringBuffer strB = new StringBuffer();// 用于存储某个文件中需要的信息 上一行

    public static void main(String args[]) throws IOException {
        String filePath = "H:\startdima\2016_06_27_13_29_58_ap_log\sdcard";
        new FindInfo1().getFiles(filePath);
    }

    private void getFiles(String filePath) throws IOException {
        File root = new File(filePath);
        File[] files = root.listFiles();
        for (File file : files) {
            String path = "";
            if (file.isDirectory()) {
                path = file.getAbsolutePath();
                getFiles(path);
                filelist.add(path);
            } else {
                path = file.getAbsolutePath();

                if (path.contains("anr") || path.contains("crash")) {
                    System.out.println(path);
                    @SuppressWarnings("resource")
                    BufferedReader bf = new BufferedReader(
                            new InputStreamReader(new FileInputStream(path)));
                    String line = "";
                    while ((line = bf.readLine()) != null) {
                        strA.append(line);
                        str.append(strA);
                        str.append(strB);
                        strString = str.toString();
                        if (str.toString().contains("Process")
                                && str.toString().contains("Flags")) {
                            int index1 = strString.indexOf("Process") + 7;
                            int index2 = strString.indexOf("Flags") + 5;
                            if (index1 < index2) {
                                strString = str.substring(index1, index2);
                                System.out.println("输出:"+strString);
                            }
                        }
                        strB = new StringBuffer("") ; 
                        strB.append(line);
                        strA = new StringBuffer("") ;
                        str = new StringBuffer("") ;
                    }
                }
            }
        }
    }
}
           

之后可以正常处理文件比较大的了,比之前效果快太多了。如果有任何好的建议或者疑问,可以撩我哦。